[RS6000] PR72802 part 2, reload ICE
[official-gcc.git] / libcilkrts / runtime / cilk_fiber.h
blobd91687aa57a237a731e28fddb756205221f30276
1 /* cilk_fiber.h -*-C++-*-
3 *************************************************************************
5 * Copyright (C) 2012-2016, Intel Corporation
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
32 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * *********************************************************************
37 * PLEASE NOTE: This file is a downstream copy of a file mainitained in
38 * a repository at cilkplus.org. Changes made to this file that are not
39 * submitted through the contribution process detailed at
40 * http://www.cilkplus.org/submit-cilk-contribution will be lost the next
41 * time that a new version is released. Changes only submitted to the
42 * GNU compiler collection or posted to the git repository at
43 * https://bitbucket.org/intelcilkruntime/intel-cilk-runtime.git are
44 * not tracked.
46 * We welcome your contributions to this open source project. Thank you
47 * for your assistance in helping us improve Cilk Plus.
48 **************************************************************************/
50 /**
51 * @file cilk_fiber.h
53 * @brief Abstraction of a "fiber": A coprocess-like stack and auxiliary data
56 #ifndef INCLUDED_CILK_FIBER_DOT_H
57 #define INCLUDED_CILK_FIBER_DOT_H
59 #include <cilk/common.h>
60 #ifdef __cplusplus
61 # include <cstddef>
62 #else
63 # include <stddef.h>
64 #endif
66 #include "bug.h"
67 #include "cilk-tbb-interop.h"
68 #include "spin_mutex.h"
69 #include "internal/abi.h" // Define __cilkrts_stack_frame
71 /**
72 * @brief Debugging level for Cilk fiber code.
74 * A value of 0 means no debugging.
75 * Higher values generate more debugging output.
77 #define FIBER_DEBUG 0
79 /**
80 * @brief Flag for validating reference counts.
82 * Set to 1 to assert that fiber reference counts are reasonable.
84 #define FIBER_CHECK_REF_COUNTS 1
86 /**
87 * @brief Flag to determine whether fibers support reference counting.
88 * We require reference counting only on Windows, for exception
89 * processing. Unix does not need reference counting.
91 #if defined(_WIN32)
92 # define NEED_FIBER_REF_COUNTS 1
93 #endif
95 /**
96 * @brief Flag to enable support for the
97 * cilk_fiber_get_current_fiber() method.
99 * I'd like this flag to be 0. However, the cilk_fiber test depends
100 * on being able to call this method.
102 #if !defined(SUPPORT_GET_CURRENT_FIBER)
103 # define SUPPORT_GET_CURRENT_FIBER 0
104 #endif
107 * @brief Switch for enabling "fast path" check for fibers, which
108 * doesn't go to the heap or OS until checking the ancestors first.
110 * Doing this check seems to make the stress test in
111 * cilk_fiber_pool.t.cpp run faster. But it doesn't seem to make much
112 * difference in other benchmarks, so it is disabled by default.
114 #define USE_FIBER_TRY_ALLOCATE_FROM_POOL 0
117 __CILKRTS_BEGIN_EXTERN_C
119 /// @brief Forward reference to fiber pool.
120 typedef struct cilk_fiber_pool cilk_fiber_pool;
122 /** @brief Opaque data structure representing a fiber */
123 typedef struct cilk_fiber cilk_fiber;
125 /** @brief Function pointer type for use as a fiber's "main" procedure */
126 typedef void (*cilk_fiber_proc)(cilk_fiber*);
128 /** @brief Data structure associated with each fiber. */
129 typedef struct cilk_fiber_data
131 __STDNS size_t stack_size; /**< Size of stack for fiber */
132 __cilkrts_worker* owner; /**< Worker using this fiber */
133 __cilkrts_stack_frame* resume_sf; /**< Stack frame to resume */
134 __cilk_tbb_pfn_stack_op stack_op_routine; /**< Cilk/TBB interop callback */
135 void* stack_op_data; /**< Data for Cilk/TBB callback */
136 void* client_data; /**< Data managed by client */
138 #ifdef _WIN32
139 char *initial_sp; /**< Initalized in fiber_stub */
140 # ifdef _WIN64
141 char *steal_frame_sp; /**< RSP for frame stealing work */
142 // Needed for exception handling so we can
143 // identify when about to unwind off stack
144 # endif
145 #endif
147 } cilk_fiber_data;
149 /** @brief Pool of cilk_fiber for fiber reuse
151 * Pools form a hierarchy, with each pool pointing to its parent. When the
152 * pool undeflows, it gets a fiber from its parent. When a pool overflows,
153 * it returns some fibers to its parent. If the root pool underflows, it
154 * allocates and initializes a new fiber from the heap but only if the total
155 * is less than max_size; otherwise, fiber creation fails.
157 struct cilk_fiber_pool
159 spin_mutex* lock; ///< Mutual exclusion for pool operations
160 __STDNS size_t stack_size; ///< Size of stacks for fibers in this pool.
161 cilk_fiber_pool* parent; ///< @brief Parent pool.
162 ///< If this pool is empty, get from parent
164 // Describes inactive fibers stored in the pool.
165 cilk_fiber** fibers; ///< Array of max_size fiber pointers
166 unsigned max_size; ///< Limit on number of fibers in pool
167 unsigned size; ///< Number of fibers currently in the pool
169 // Statistics on active fibers that were allocated from this pool,
170 // but no longer in the pool.
171 int total; ///< @brief Fibers allocated - fiber deallocated from pool
172 ///< total may be negative for non-root pools.
173 int high_water; ///< High water mark of total fibers
174 int alloc_max; ///< Limit on number of fibers allocated from the heap/OS
177 /** @brief Initializes a cilk_fiber_pool structure
179 * @param pool - The address of the pool that is to be initialized
180 * @param parent - The address of this pool's parent, or NULL for root pool
181 * @param stack_size - Size of stacks for fibers allocated from this pool.
182 * @param buffer_size - The maximum number of fibers that may be pooled.
183 * @param alloc_max - Limit on # of fibers this pool can allocate from the heap.
184 * @param is_shared - True if accessing this pool needs a lock, false otherwise.
186 void cilk_fiber_pool_init(cilk_fiber_pool* pool,
187 cilk_fiber_pool* parent,
188 size_t stack_size,
189 unsigned buffer_size,
190 int alloc_max,
191 int is_shared);
193 /** @brief Sets the maximum number of fibers to allocate from a root pool.
195 * @param root_pool - A root fiber pool
196 * @param max_fibers_to_allocate - The limit on # of fibers to allocate.
198 * Sets the maximum number of fibers that can be allocated from this
199 * pool and all its descendants. This pool must be a root pool.
201 void cilk_fiber_pool_set_fiber_limit(cilk_fiber_pool* root_pool,
202 unsigned max_fibers_to_allocate);
204 /** @brief De-initalizes a cilk_fiber_pool
206 * @param pool - The address of the pool that is to be destroyed
208 void cilk_fiber_pool_destroy(cilk_fiber_pool* pool);
210 /** @brief Allocates a new cilk_fiber.
212 * If the specified pool is empty, this method may choose to either
213 * allocate a fiber from the heap (if pool->total < pool->alloc_max),
214 * or retrieve a fiber from the parent pool.
216 * @note If a non-null fiber is returned, @c cilk_fiber_reset_state
217 * should be called on this fiber before using it.
219 * An allocated fiber begins with a reference count of 1.
220 * This method may lock @c pool or one of its ancestors.
222 * @pre pool should not be NULL.
224 * @param pool The fiber pool from which to retrieve a fiber.
225 * @return An allocated fiber, or NULL if failed to allocate.
227 cilk_fiber* cilk_fiber_allocate(cilk_fiber_pool* pool);
229 /** @brief Allocate and initialize a new cilk_fiber using memory from
230 * the heap and/or OS.
232 * The allocated fiber begins with a reference count of 1.
234 * @param stack_size The size (in bytes) to be allocated for the fiber's
235 * stack.
236 * @return An initialized fiber. This method should not return NULL
237 * unless some exceptional condition has occurred.
239 cilk_fiber* cilk_fiber_allocate_from_heap(size_t stack_size);
242 /** @brief Resets an fiber object just allocated from a pool with the
243 * specified proc.
245 * After this call, cilk_fiber_data object associated with this fiber
246 * is filled with zeros.
248 * This function can be called only on a fiber that has been allocated
249 * from a pool, but never used.
251 * @param fiber The fiber to reset and initialize.
252 * @param start_proc The function to run when switching to the fiber. If
253 * null, the fiber can be used with cilk_fiber_run_proc()
254 * but not with cilk_fiber_resume().
256 void cilk_fiber_reset_state(cilk_fiber* fiber,
257 cilk_fiber_proc start_proc);
259 /** @brief Remove a reference from this fiber, possibly deallocating it.
261 * This fiber is deallocated only when there are no other references
262 * to it. Deallocation happens either by returning the fiber to the
263 * specified pool, or returning it to the heap.
265 * A fiber that is currently executing should not remove the last
266 * reference to itself.
268 * When a fiber is deallocated, destructors are not called for the
269 * objects (if any) still on its stack. The fiber's stack and fiber
270 * data is returned to the stack pool but the client fiber data is not
271 * deallocated.
273 * If the pool overflows because of a deallocation, then some fibers
274 * will be returned to the parent pool. If the root pool overflows,
275 * then the fiber is returned to the heap.
277 * @param fiber The Cilk fiber to remove a reference to.
278 * @param pool The fiber pool to which the fiber should be returned. The
279 * caller is assumed to have exclusive access to the pool
280 * either because there is no contention for it or because
281 * its lock has been acquired. If pool is NULL, any
282 * deallocated fiber is destroyed and returned to the
283 * heap.
285 * @return Final reference count. If the count is 0, the fiber was
286 * returned to a pool or the heap.
288 int cilk_fiber_remove_reference(cilk_fiber *fiber, cilk_fiber_pool *pool);
290 /** @brief Allocates and intializes this thread's main fiber
292 * Each thread has an "implicit" main fiber that control's the
293 * thread's initial stack. This function makes this fiber visible to
294 * the client and allocates the Cilk-specific aspects of the implicit
295 * fiber. A call to this function must be paired with a call to
296 * cilk_fiber_deallocate_fiber_from_thread()
297 * or a memory leak (or worse) will result.
299 * A fiber allocated from a thread begins with a reference count of 2.
300 * One is for being allocated, and one is for being active.
301 * (A fiber created from a thread is automatically currently executing.)
302 * The matching calls above each decrement the reference count by 1.
304 * @return A fiber for the currently executing thread.
306 cilk_fiber* cilk_fiber_allocate_from_thread(void);
308 /** @brief Remove a fiber created from a thread,
309 * possibly deallocating it.
311 * Same as cilk_fiber_remove_reference, except that it works on fibers
312 * created via cilk_fiber_allocate_from_thread().
314 * Fibers created from a thread are never returned to a pool.
316 * @param fiber The Cilk fiber to remove a reference from.
317 * @return Final reference count. If the count is 0, the fiber was
318 * returned to the heap.
320 int cilk_fiber_remove_reference_from_thread(cilk_fiber *fiber);
322 /** @brief Deallocate a fiber created from a thread,
323 * possibly destroying it.
325 * This method decrements the reference count of the fiber by 2, and
326 * destroys the fiber struct if the reference count is 0.
328 * OS-specific cleanup for the fiber executes unconditionally with
329 * this method. The destruction of the actual object, however, does
330 * not occur unless the reference count is 0.
332 * @param fiber The cilk_fiber to deallocate from a thread.
333 * @return Final reference count. If the count is 0, the fiber was
334 * returned to the heap.
336 int cilk_fiber_deallocate_from_thread(cilk_fiber *fiber);
338 /** @brief Returns true if this fiber is allocated from a thread.
340 int cilk_fiber_is_allocated_from_thread(cilk_fiber *fiber);
343 /** @brief Suspend execution on current fiber resumes other fiber.
345 * Suspends the current fiber and transfers control to a new fiber. Execution
346 * on the new fiber resumes from the point at which fiber suspended itself to
347 * run a different fiber. If fiber was freshly allocated, then runs the
348 * start_proc function specified at allocation. This function returns when
349 * another fiber resumes the self fiber. Note that the state of the
350 * floating-point control register (i.e., the register that controls rounding
351 * mode, etc.) is valid but indeterminate on return -- different
352 * implementations will have different results.
354 * When the @c self fiber is resumed, execution proceeds as though
355 * this function call returns.
357 * This operation increments the reference count of @p other.
358 * This operation decrements the reference count of @p self.
360 * @param self Fiber to switch from. Must equal current fiber.
361 * @param other Fiber to switch to.
363 void cilk_fiber_suspend_self_and_resume_other(cilk_fiber* self,
364 cilk_fiber* other);
366 /** @brief Removes a reference from the currently executing fiber and
367 * resumes other fiber.
369 * Removes a reference from @p self and transfer control to @p other
370 * fiber. Execution on @p other resumes from the point at which @p
371 * other suspended itself to run a different fiber. If @p other fiber
372 * was freshly allocated, then runs the function specified at
373 * creation.
376 * This operation increments the reference count of @p other.
378 * This operation conceptually decrements the reference count of
379 * @p self twice, once to suspend it, and once to remove a reference to
380 * it. Then, if the count is 0, it is returned to the specified pool
381 * or destroyed.
383 * @pre @p self is the currently executing fiber.
385 * @param self Fiber to remove reference switch from.
386 * @param self_pool Pool to which the current fiber should be returned
387 * @param other Fiber to switch to.
389 NORETURN
390 cilk_fiber_remove_reference_from_self_and_resume_other(cilk_fiber* self,
391 cilk_fiber_pool* self_pool,
392 cilk_fiber* other);
394 /** @brief Set the proc method to execute immediately after a switch
395 * to this fiber.
397 * The @c post_switch_proc method executes immediately after switching
398 * away form @p self fiber to some other fiber, but before @c self
399 * gets cleaned up.
401 * @note A fiber can have only one post_switch_proc method at a time.
402 * If this method is called multiple times before switching to the
403 * fiber, only the last proc method will execute.
405 * @param self Fiber.
406 * @param post_switch_proc Proc method to execute immediately after switching to this fiber.
408 void cilk_fiber_set_post_switch_proc(cilk_fiber* self, cilk_fiber_proc post_switch_proc);
410 /** @brief Invoke TBB stack op for this fiber.
412 * @param fiber Fiber to invoke stack op for.
413 * @param op The stack op to invoke
415 void cilk_fiber_invoke_tbb_stack_op(cilk_fiber* fiber, __cilk_tbb_stack_op op);
417 /** @brief Returns the fiber data associated with the specified fiber.
419 * The returned struct is owned by the fiber and is deallocated automatically
420 * when the fiber is destroyed. However, the client_data field is owned by
421 * the client and must be deallocated separately. When called for a
422 * newly-allocated fiber, the returned data is zero-filled.
424 * @param fiber The fiber for which data is being requested.
425 * @return The fiber data for the specified fiber
427 cilk_fiber_data* cilk_fiber_get_data(cilk_fiber* fiber);
429 /** @brief Retrieve the owner field from the fiber.
431 * This method is provided for convenience. One can also get the
432 * fiber data, and then get the owner field.
434 __CILKRTS_INLINE
435 __cilkrts_worker* cilk_fiber_get_owner(cilk_fiber* fiber)
437 // TBD: We really want a static assert here, that this cast is
438 // doing the right thing.
439 cilk_fiber_data* fdata = (cilk_fiber_data*)fiber;
440 return fdata->owner;
443 /** @brief Sets the owner field of a fiber.
445 * This method is provided for convenience. One can also get the
446 * fiber data, and then get the owner field.
448 __CILKRTS_INLINE
449 void cilk_fiber_set_owner(cilk_fiber* fiber, __cilkrts_worker* owner)
451 // TBD: We really want a static assert here, that this cast is
452 // doing the right thing.
453 cilk_fiber_data* fdata = (cilk_fiber_data*)fiber;
454 fdata->owner = owner;
457 /** @brief Returns true if this fiber is resumable.
459 * A fiber is considered resumable when it is not currently being
460 * executed.
462 * This function is used by Windows exception code.
463 * @param fiber The fiber to check.
464 * @return Nonzero value if fiber is resumable.
466 int cilk_fiber_is_resumable(cilk_fiber* fiber);
469 * @brief Returns the base of this fiber's stack.
471 * On some platforms (e.g., Windows), the fiber must have started
472 * running before we can get this information.
474 * @param fiber The fiber to get the stack pointer from.
475 * @return The base of the stack, or NULL if this
476 * information is not available yet.
478 char* cilk_fiber_get_stack_base(cilk_fiber* fiber);
481 /****************************************************************************
482 * TBB interop functions
483 * **************************************************************************/
485 * @brief Set the TBB callback information for a stack
487 * @param fiber The fiber to set the TBB callback information for
488 * @param o The TBB callback thunk. Specifies the callback address and
489 * context value.
491 void cilk_fiber_set_stack_op(cilk_fiber *fiber,
492 __cilk_tbb_stack_op_thunk o);
495 * @brief Save the TBB callback address and context value in
496 * thread-local storage.
498 * We'll use it later when the thread binds to a worker.
500 * @param o The TBB callback thunk which is to be saved.
502 void cilk_fiber_tbb_interop_save_stack_op_info(__cilk_tbb_stack_op_thunk o);
505 * @brief Move TBB stack-op info from thread-local storage and store
506 * it into the fiber.
508 * Called when we bind a thread to the runtime. If there is any TBB
509 * interop information in thread-local storage, bind it to the stack
510 * now.
512 * @pre \c fiber should not be NULL.
513 * @param fiber The fiber that should take over the TBB interop information.
515 void cilk_fiber_tbb_interop_use_saved_stack_op_info(cilk_fiber *fiber);
518 * @brief Free any TBB interop information saved in thread-local storage
520 void cilk_fiber_tbb_interop_free_stack_op_info(void);
523 * @brief Migrate any TBB interop information from a cilk_fiber to
524 * thread-local storage.
526 * Returns immediately if no TBB interop information has been
527 * associated with the stack.
529 * @param fiber The cilk_fiber who's TBB interop information should be
530 * saved in thread-local storage.
532 void cilk_fiber_tbb_interop_save_info_from_stack(cilk_fiber* fiber);
535 #if SUPPORT_GET_CURRENT_FIBER
536 /** @brief Returns the fiber associated with the currently executing thread
538 * @note This function is currently used only for testing the Cilk
539 * runtime.
541 * @return Fiber associated with the currently executing thread or NULL if no
542 * fiber was associated with this thread.
544 cilk_fiber* cilk_fiber_get_current_fiber(void);
545 #endif
548 #if NEED_FIBER_REF_COUNTS
549 /** @brief Returns true if this fiber has reference count > 0.
551 * @param fiber The fiber to check for references.
552 * @return Nonzero value if the fiber has references.
554 int cilk_fiber_has_references(cilk_fiber *fiber);
556 /** @brief Returns the value of the reference count.
558 * @param fiber The fiber to check for references.
559 * @return The value of the reference count of fiber.
561 int cilk_fiber_get_ref_count(cilk_fiber *fiber);
563 /** @brief Adds a reference to this fiber.
565 * Increments the reference count of a current fiber. Fibers with
566 * nonzero reference count will not be freed or returned to a fiber
567 * pool.
569 * @param fiber The fiber to add a reference to.
571 void cilk_fiber_add_reference(cilk_fiber *fiber);
573 #endif // NEED_FIBER_REF_COUNTS
575 __CILKRTS_END_EXTERN_C
577 #ifdef __cplusplus
578 // Some C++ implementation details
580 /// Opaque declaration of a cilk_fiber_sysdep object.
581 struct cilk_fiber_sysdep;
584 * cilk_fiber is a base-class for system-dependent fiber implementations.
586 struct cilk_fiber : protected cilk_fiber_data
588 protected:
589 // This is a rare acceptable use of protected inheritence and protected
590 // variable access: when the base class and derived class collaborate
591 // tightly to comprise a single component.
593 /// For overloading constructor of cilk_fiber.
594 enum from_thread_t { from_thread = 1 };
596 // Boolean flags capturing the status of the fiber.
597 // Each one can be set independently.
598 // A default fiber is constructed with a flag value of 0.
599 static const int RESUMABLE = 0x01; ///< True if the fiber is in a suspended state and can be resumed.
600 static const int ALLOCATED_FROM_THREAD = 0x02; ///< True if fiber was allocated from a thread.
602 cilk_fiber_proc m_start_proc; ///< Function to run on start up/reset
603 cilk_fiber_proc m_post_switch_proc; ///< Function that executes when we first switch to a new fiber from a different one.
605 cilk_fiber* m_pending_remove_ref;///< Fiber to possibly delete on start up or resume
606 cilk_fiber_pool* m_pending_pool; ///< Pool where m_pending_remove_ref should go if it is deleted.
607 unsigned m_flags; ///< Captures the status of this fiber.
609 #if NEED_FIBER_REF_COUNTS
610 volatile long m_outstanding_references; ///< Counts references to this fiber.
611 #endif
613 /// Creates a fiber with NULL data.
614 cilk_fiber();
617 * @brief Creates a fiber with user-specified arguments.
619 * @param stack_size Size of stack to use for this fiber.
621 cilk_fiber(std::size_t stack_size);
623 /// Empty destructor.
624 ~cilk_fiber();
627 * @brief Performs any actions that happen after switching from
628 * one fiber to another.
630 * These actions are:
631 * 1. Execute m_post_switch_proc on a fiber.
632 * 2. Do any pending deallocations from the previous fiber.
634 void do_post_switch_actions();
637 *@brief Helper method that converts a @c cilk_fiber object into a
638 * @c cilk_fiber_sysdep object.
640 * The @c cilk_fiber_sysdep object contains the system-dependent parts
641 * of the implementation of a @\c cilk_fiber.
643 * We could have @c cilk_fiber_sysdep inherit from @c cilk_fiber and
644 * then use virtual functions. But since a given platform only uses
645 * one definition of @c cilk_fiber_sysdep at a time, we statically
646 * cast between them.
648 inline cilk_fiber_sysdep* sysdep();
651 * @brief Set resumable flag to specified state.
653 inline void set_resumable(bool state) {
654 m_flags = state ? (m_flags | RESUMABLE) : (m_flags & (~RESUMABLE));
658 *@brief Set the allocated_from_thread flag.
660 inline void set_allocated_from_thread(bool state) {
661 m_flags = state ? (m_flags | ALLOCATED_FROM_THREAD) : (m_flags & (~ALLOCATED_FROM_THREAD));
664 public:
667 * @brief Allocates and initializes a new cilk_fiber, either from
668 * the specified pool or from the heap.
670 * @pre pool should not be NULL.
672 static cilk_fiber* allocate(cilk_fiber_pool* pool);
675 * @brief Allocates a fiber from the heap.
677 static cilk_fiber* allocate_from_heap(size_t stack_size);
680 * @brief Return a fiber to the heap.
682 void deallocate_to_heap();
685 * @brief Reset the state of a fiber just allocated from a pool.
687 void reset_state(cilk_fiber_proc start_proc);
690 * @brief Remove a reference from this fiber, possibly
691 * deallocating it if the reference count becomes 0.
693 * @param pool The fiber pool to which this fiber should be returned.
694 * @return The final reference count.
696 int remove_reference(cilk_fiber_pool* pool);
699 * @brief Deallocate the fiber by returning it to the pool.
700 * @pre This method should only be called if the reference count
701 * is 0.
703 * @param pool The fiber pool to return this fiber to. If NULL,
704 * fiber is returned to the heap.
706 void deallocate_self(cilk_fiber_pool *pool);
708 /** @brief Allocates and intializes this thread's main fiber. */
709 static cilk_fiber* allocate_from_thread();
711 /** @brief Deallocate a fiber created from a thread,
712 * possibly destroying it.
714 * This method decrements the reference count of this fiber by 2,
715 * and destroys the fiber if the reference count is 0.
717 * OS-specific cleanup for the fiber executes unconditionally with for
718 * this method. The destruction of the actual object, however, does
719 * not occur unless the reference count is 0.
721 * @return Final reference count. If the count is 0, the fiber was
722 * returned to the heap.
724 int deallocate_from_thread();
726 /** @brief Removes a reference from this fiber.
728 * This method deallocates this fiber if the reference count
729 * becomes 0.
731 * @pre This fiber must be allocated from a thread.
732 * @return The final reference count of this fiber.
734 int remove_reference_from_thread();
736 #if SUPPORT_GET_CURRENT_FIBER
737 /** @brief Get the current fiber from TLS.
739 * @note This function is only used for testing the runtime.
741 static cilk_fiber* get_current_fiber();
742 #endif
744 /** @brief Suspend execution on current fiber resumes other fiber.
746 * Control returns after resuming execution of the self fiber.
748 void suspend_self_and_resume_other(cilk_fiber* other);
751 /** @brief Removes a reference from the currently executing fiber
752 * and resumes other fiber.
754 * This fiber may be returned to a pool or deallocated.
756 NORETURN remove_reference_from_self_and_resume_other(cilk_fiber_pool* self_pool,
757 cilk_fiber* other);
759 /** @brief Set the proc method to execute immediately after a switch
760 * to this fiber.
762 * @param post_switch_proc Proc method to execute immediately
763 * after switching to this fiber.
765 inline void set_post_switch_proc(cilk_fiber_proc post_switch_proc) {
766 m_post_switch_proc = post_switch_proc;
769 /** @brief Returns true if this fiber is resumable.
771 * A fiber is considered resumable when it is not currently being
772 * executed.
774 inline bool is_resumable(void) {
775 return (m_flags & RESUMABLE);
778 /** @brief Returns true if fiber was allocated from a thread. */
779 inline bool is_allocated_from_thread(void) {
780 return (m_flags & ALLOCATED_FROM_THREAD);
784 *@brief Get the address at the base of the stack for this fiber.
786 inline char* get_stack_base();
788 /** @brief Return the data for this fiber. */
789 cilk_fiber_data* get_data() { return this; }
791 /** @brief Return the data for this fiber. */
792 cilk_fiber_data const* get_data() const { return this; }
795 #if NEED_FIBER_REF_COUNTS
796 /** @brief Verifies that this fiber's reference count equals v. */
797 inline void assert_ref_count_equals(long v) {
798 #if FIBER_CHECK_REF_COUNTS
799 CILK_ASSERT(m_outstanding_references >= v);
800 #endif
803 /** @brief Verifies that this fiber's reference count is at least v. */
804 inline void assert_ref_count_at_least(long v) {
805 #if FIBER_CHECK_REF_COUNTS
806 CILK_ASSERT(m_outstanding_references >= v);
807 #endif
810 /** @brief Get reference count. */
811 inline long get_ref_count() { return m_outstanding_references; }
813 /** @brief Initialize reference count.
814 * Operation is not atomic.
816 inline void init_ref_count(long v) { m_outstanding_references = v; }
818 // For Windows, updates to the fiber reference count need to be
819 // atomic, because exceptions can live on a stack that we are not
820 // currently executing on. Thus, we can update the reference
821 // count of a fiber we are not currently executing on.
823 /** @brief Increment reference count for this fiber [Windows]. */
824 inline void inc_ref_count() { atomic_inc_ref_count(); }
826 /** @brief Decrement reference count for this fiber [Windows]. */
827 inline long dec_ref_count() { return atomic_dec_ref_count(); }
829 /** @brief Subtract v from the reference count for this fiber [Windows]. */
830 inline long sub_from_ref_count(long v) { return atomic_sub_from_ref_count(v); }
831 #else // NEED_FIBER_REF_COUNTS
833 // Without reference counting, we have placeholder methods.
834 inline void init_ref_count(long v) { }
836 inline void inc_ref_count() { }
838 // With no reference counting, dec_ref_count always return 0.
839 // Thus, anyone checking is always the "last" one.
840 inline long dec_ref_count() { return 0; }
841 inline long sub_from_ref_count(long v) { return 0; }
843 // The assert methods do nothing.
844 inline void assert_ref_count_equals(long v) { }
845 inline void assert_ref_count_at_least(long v) { }
846 #endif
849 * @brief Call TBB to tell it about an "interesting" event.
851 * @param op Value specifying the event to track.
853 void invoke_tbb_stack_op(__cilk_tbb_stack_op op);
855 private:
858 * @brief Helper method: try to allocate a fiber from this pool or
859 * its ancestors without going to the OS / heap.
861 * Returns allocated pool, or NULL if no pool is found.
863 * If pool contains a suitable fiber. Return it. Otherwise, try to
864 * recursively grab a fiber from the parent pool, if there is one.
866 * This method will not allocate a fiber from the heap.
868 static cilk_fiber* try_allocate_from_pool_recursive(cilk_fiber_pool* pool);
871 #if NEED_FIBER_REF_COUNTS
873 * @brief Atomic increment of reference count.
875 void atomic_inc_ref_count();
878 * @brief Atomic decrement of reference count.
880 long atomic_dec_ref_count();
883 * @brief Atomic subtract of v from reference count.
884 * @param v Value to subtract.
886 long atomic_sub_from_ref_count(long v);
887 #endif // NEED_FIBER_REF_COUNTS
891 #endif // __cplusplus
893 #endif // ! defined(INCLUDED_CILK_FIBER_DOT_H)