1/* 2 * abi.h 3 * 4 * @copyright 5 * Copyright (C) 2009-2013, Intel Corporation 6 * All rights reserved. 7 * 8 * @copyright 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * * Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * * Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * * Neither the name of Intel Corporation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * @copyright 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 31 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 34 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 * 37 ******************************************************************************/ 38 39/** 40 * @file abi.h 41 * 42 * @brief Defines the application binary interface between the compiler and 43 * the Intel Cilk Plus runtime. 44 */ 45 46#ifndef CILK_INTERNAL_ABI_H 47#define CILK_INTERNAL_ABI_H 48 49 50#include <cilk/common.h> 51#include <stddef.h> // Needed to define size_t 52 53/** 54 * Jump buffers are OS and architecture dependent 55 */ 56#if ! defined(_MSC_VER) 57/* Non-Windows - only need 5 registers for the jump buffer for both IA32 and Intel64 */ 58typedef void *__CILK_JUMP_BUFFER[5]; 59 60/** OS-specific implementation of setjmp */ 61# define CILK_SETJMP(X) __builtin_setjmp(X) 62/** OS-specific implementation of longjmp */ 63# define CILK_LONGJMP(X) __builtin_longjmp(X,1) 64#else 65/* Windows - things are a little more complicated */ 66# if defined(_M_X64) 67/* Intel64 - Use an OS-defined jump buffer */ 68# include <setjmp.h> 69typedef jmp_buf __CILK_JUMP_BUFFER; 70 71# define CILK_SETJMP(X) setjmp(X) 72# define CILK_LONGJMP(X) longjmp(X, 1) 73# elif defined(_M_IX86) 74/** 75 * Windows x86 - Use a simplified version of the Windows jump buffer for x86 76 * setjmp is provided by __cilkrts_setjmp which passes jump buffer in EAX and 77 * destination in EDX longjmp is provided by an internal routine which uses 78 * this structure 79 */ 80typedef struct 81{ 82 unsigned long Ebp; 83 unsigned long Ebx; 84 unsigned long Edi; 85 unsigned long Esi; 86 unsigned long Esp; 87 unsigned long Eip; 88 unsigned long Registration; 89 unsigned long TryLevel; 90} __CILK_JUMP_BUFFER; 91 92# else 93# error Unexpected architecture - Need to define __CILK_JUMP_BUFFER 94# endif /* _M_X64 */ 95 96#endif /* defined(_MSC_VER) */ 97 98/* struct tags */ 99typedef struct __cilkrts_stack_frame __cilkrts_stack_frame; ///< struct tag for stack frame 100 101// Forwarded declarations 102typedef struct global_state_t global_state_t; ///< Forwarded declaration for global state 103typedef struct local_state local_state; ///< Forwarded declaration for local state 104typedef struct cilkred_map cilkred_map; ///< Forward declaration for reducer map 105 106/// Forwarded declaration for system-dependent worker state 107typedef struct __cilkrts_worker_sysdep_state 108 __cilkrts_worker_sysdep_state; 109 110/** 111 * The worker struct contains per-worker information that needs to be 112 * visible to the compiler, or rooted here. 113 * 114 * For 32-bit Windows we need to be aligning the structures on 4-byte 115 * boundaries to match where ICL is allocating the birthrank and rank 116 * in the __cilkrts_stack_frame. It's 4-byte aligned instead of 8-byte 117 * aligned. This is OK because the compiler is dealing with the 64-bit 118 * quantities as two 32-bit values. So change the packing to be on 119 * 4-byte boundaries. 120 * 121 * The fields of the worker struct can be classified as either local 122 * or shared. 123 * 124 * Local: This field is only accessed by the thread bound to this 125 * worker struct. Local fields can be freely accessed without 126 * acquiring locks. 127 * 128 * Shared: This field may be accessed by multiple worker threads. 129 * Accesses to shared fields usually requires locks, except in 130 * special situations where one can prove that locks are 131 * unnecessary. 132 * 133 * The fields of the worker struct can also be classified as 134 * "read-only" if the field does not change after it is initialized. 135 * Otherwise, the field is "read/write". Read-only fields do not 136 * require locks to access (ignoring the synchronization that might be 137 * needed for initialization if this can occur in parallel). 138 * 139 * Finally, we explicitly classify some fields as "synchronization" 140 * fields if they are used as part of a synchronization protocol in 141 * the runtime. These variables are generally shared and read/write. 142 * Mostly, this category includes lock variables and other variables 143 * that are involved in synchronization protocols (i.e., the THE 144 * protocol). 145 */ 146#if defined(_MSC_VER) && defined(_M_IX86) 147#pragma pack(push, 4) 148#endif 149 150struct __cilkrts_worker { 151 /** 152 * T, H, and E pointers in the THE protocol See "The implementation of 153 * the Cilk-5 multithreaded language", PLDI 1998: 154 * http://portal.acm.org/citation.cfm?doid=277652.277725 155 * 156 * Synchronization fields. [shared read/write] 157 */ 158 __cilkrts_stack_frame *volatile *volatile tail; 159 __cilkrts_stack_frame *volatile *volatile head; /**< @copydoc tail */ 160 __cilkrts_stack_frame *volatile *volatile exc; /**< @copydoc tail */ 161 162 /** 163 * Addition to the THE protocol to allow us to protect some set of 164 * entries in the tail queue from stealing. Normally, this is set 165 * beyond the end of the task queue, indicating that all entries are 166 * available for stealing. During exception handling, protected_tail 167 * may be set to the first entry in the task queue, indicating that 168 * stealing is not allowed. 169 * 170 * Synchronization field. 171 */ 172 __cilkrts_stack_frame *volatile *volatile protected_tail; 173 174 /** 175 * Limit of the Lazy Task Queue, to detect queue overflow 176 * [local read-only] 177 */ 178 __cilkrts_stack_frame *volatile *ltq_limit; 179 180 /** 181 * Worker id. 182 * [local read-only] 183 */ 184 int32_t self; 185 186 /** 187 * Global state of the runtime system, opaque to the client. 188 * [local read-only] 189 */ 190 global_state_t *g; 191 192 /** 193 * Additional per-worker state of the runtime system that we want 194 * to maintain hidden from the client. 195 * [shared read-only] 196 */ 197 local_state *l; 198 199 /** 200 * Map from reducer names to reducer values. 201 * [local read/write] 202 */ 203 cilkred_map *reducer_map; 204 205 /** 206 * A slot that points to the currently executing Cilk frame. 207 * [local read/write] 208 */ 209 __cilkrts_stack_frame *current_stack_frame; 210 211 /** 212 * Reserved space for a pointer. 213 * Used to be __cilkrts_stack_frame *volatile *volatile saved_protected_tail; 214 */ 215 void* reserved; 216 217 /** 218 * System-dependent part of the worker state 219 * [local read-only] 220 */ 221 __cilkrts_worker_sysdep_state *sysdep; 222 223#if __CILKRTS_ABI_VERSION >= 1 224 /** 225 * Per-worker pedigree information used to support scheduling-independent 226 * pseudo-random numbers. 227 * [local read/write] 228 */ 229 __cilkrts_pedigree pedigree; 230#endif /* __CILKRTS_ABI_VERSION >= 1 */ 231}; 232 233 234/** 235 * Every spawning function has a frame descriptor. A spawning function 236 * is a function that spawns or detaches. Only spawning functions 237 * are visible to the Cilk runtime. 238 */ 239struct __cilkrts_stack_frame 240{ 241 /** 242 * flags is an integer with values defined below. Client code 243 * initializes flags to CILK_FRAME_VERSION before the first Cilk 244 * operation. 245 * 246 * The low 24-bits of the 'flags' field are the flags, proper. The high 247 * 8-bits are the version number. 248 * 249 * IMPORTANT: bits in this word are set and read by the PARENT ONLY, 250 * not by a spawned child. In particular, the STOLEN and UNSYNCHED 251 * bits are set on a steal and are read before a sync. Since there 252 * is no synchronization (locking) on this word, any attempt to set 253 * or read these bits asynchronously in a child would result in a race. 254 */ 255 uint32_t flags; 256 257 /** Not currently used. Not initialized by Intel compiler. */ 258 int32_t size; 259 260 /** 261 * call_parent points to the __cilkrts_stack_frame of the closest 262 * ancestor spawning function, including spawn helpers, of this frame. 263 * It forms a linked list ending at the first stolen frame. 264 */ 265 __cilkrts_stack_frame *call_parent; 266 267 /** 268 * The client copies the worker from TLS here when initializing 269 * the structure. The runtime ensures that the field always points 270 * to the __cilkrts_worker which currently "owns" the frame. 271 */ 272 __cilkrts_worker *worker; 273 274 /** 275 * Unix: Pending exception after sync. The sync continuation 276 * must call __cilkrts_rethrow to handle the pending exception. 277 * 278 * Windows: the handler that _would_ have been registered if our 279 * handler were not there. We maintain this for unwinding purposes. 280 * Win32: the value of this field is only defined in spawn helper 281 * functions 282 * 283 * Win64: except_data must be filled in for all functions with a 284 * __cilkrts_stack_frame 285 */ 286 void *except_data; 287 288 /** 289 * Before every spawn and nontrivial sync the client function 290 * saves its continuation here. 291 */ 292 __CILK_JUMP_BUFFER ctx; 293 294#if __CILKRTS_ABI_VERSION >= 1 295 /** 296 * Architecture-specific floating point state. mxcsr and fpcsr should be 297 * set when CILK_SETJMP is called in client code. Note that the Win64 298 * jmpbuf for the Intel64 architecture already contains this information 299 * so there is no need to use these fields on that OS/architecture. 300 */ 301 uint32_t mxcsr; 302 uint16_t fpcsr; /**< @copydoc mxcsr */ 303 304 305 /** 306 * reserved is not used at this time. Client code should initialize it 307 * to 0 before the first Cilk operation 308 */ 309 uint16_t reserved; 310 311 /** 312 * Pedigree information to support scheduling-independent pseudo-random 313 * numbers. There are two views of this information. The copy in a 314 * spawning function is used to stack the rank and communicate to the 315 * runtime on a steal or continuation. The copy in a spawn helper is 316 * immutable once the function is detached and is a node in the pedigree. 317 * The union is used to make clear which view we're using. 318 * 319 * In the detach sequence Client code should: 320 * - copy the worker pedigree into the spawn helper's pedigree 321 * - copy the worker pedigree into the call parent's pedigree 322 * - set the worker's rank to 0 323 * - set the worker's pedigree.next to the spawn helper's pedigree 324 */ 325 union 326 { 327 __cilkrts_pedigree spawn_helper_pedigree; /* Used in spawn helpers */ 328 __cilkrts_pedigree parent_pedigree; /* Used in spawning funcs */ 329 }; 330#endif /* __CILKRTS_ABI_VERSION >= 1 */ 331}; 332 333/* 334 * Restore previous structure packing for 32-bit Windows 335 */ 336#if defined(_MSC_VER) && defined(_M_IX86) 337#pragma pack(pop) 338#endif 339 340/* Values of the flags bitfield */ 341/** CILK_FRAME_STOLEN is set if the frame has ever been stolen. */ 342#define CILK_FRAME_STOLEN 0x01 343 344/** 345 * CILK_FRAME_UNSYNCHED is set if the frame has been stolen and 346 * is has not yet executed _Cilk_sync. It is technically a misnomer in that a 347 * frame can have this flag set even if all children have returned. 348 */ 349#define CILK_FRAME_UNSYNCHED 0x02 350 351/** 352 * Is this frame detached (spawned)? If so the runtime needs 353 * to undo-detach in the slow path epilogue. 354 */ 355#define CILK_FRAME_DETACHED 0x04 356 357/** 358 * CILK_FRAME_EXCEPTION_PROBED is set if the frame has been probed in the 359 * exception handler first pass 360 */ 361#define CILK_FRAME_EXCEPTION_PROBED 0x08 362 363/** Is this frame receiving an exception after sync? */ 364#define CILK_FRAME_EXCEPTING 0x10 365 366/** 367 * Is the pedigree unsynched? That is, has a synch occurred that is not 368 * yet represented in the pedigree? 369 */ 370#define CILK_FRAME_SF_PEDIGREE_UNSYNCHED 0x20 371 372/** Is this the last (oldest) Cilk frame? */ 373#define CILK_FRAME_LAST 0x80 374 375/** 376 * Is this frame in the epilogue, or more generally after the last 377 * sync when it can no longer do any Cilk operations? 378 */ 379#define CILK_FRAME_EXITING 0x0100 380 381/** Is this frame suspended? (used for debugging) */ 382#define CILK_FRAME_SUSPENDED 0x8000 383 384/** Used by Windows exception handling to indicate that __cilkrts_leave_frame should do nothing */ 385#define CILK_FRAME_UNWINDING 0x10000 386 387/* 388 * The low 24-bits of the 'flags' field are the flags, proper. The high 8-bits 389 * are the version number. 390 */ 391 392/** ABI version left shifted to the high byte */ 393#define CILK_FRAME_VERSION (__CILKRTS_ABI_VERSION << 24) 394 395/** Mask for the flags field to isolate the version bits */ 396#define CILK_FRAME_VERSION_MASK 0xFF000000 397 398/** Mask for the flags field to isolate the flag bits */ 399#define CILK_FRAME_FLAGS_MASK 0x00FFFFFF 400 401/** Convenience macro to provide access the version portion of the flags field */ 402#define CILK_FRAME_VERSION_VALUE(_flags) (((_flags) & CILK_FRAME_VERSION_MASK) >> 24) 403 404/** Any undefined bits are reserved and must be zero ("MBZ" = "Must Be Zero") */ 405#define CILK_FRAME_MBZ (~ (CILK_FRAME_STOLEN | \ 406 CILK_FRAME_UNSYNCHED | \ 407 CILK_FRAME_DETACHED | \ 408 CILK_FRAME_EXCEPTION_PROBED | \ 409 CILK_FRAME_EXCEPTING | \ 410 CILK_FRAME_SF_PEDIGREE_UNSYNCHED | \ 411 CILK_FRAME_LAST | \ 412 CILK_FRAME_EXITING | \ 413 CILK_FRAME_SUSPENDED | \ 414 CILK_FRAME_UNWINDING | \ 415 CILK_FRAME_VERSION_MASK)) 416 417__CILKRTS_BEGIN_EXTERN_C 418 419/** 420 * Call __cilkrts_enter_frame to initialize an ABI 0 frame descriptor. 421 * Initialize the frame descriptor before spawn or detach. A function that 422 * conditionally does Cilk operations need not initialize the frame descriptor 423 * in a code path that never uses it. 424 * 425 * @param sf The __cilkrts_stack_frame that is to be initialized. 426 */ 427CILK_ABI(void) __cilkrts_enter_frame(__cilkrts_stack_frame* sf); 428 429/** 430 * Call __cilkrts_enter_frame to initialize an ABI 1 frame descriptor. 431 * Initialize the frame descriptor before spawn or detach. A function that 432 * conditionally does Cilk operations need not initialize the frame descriptor 433 * in a code path that never uses it. 434 * 435 * @param sf The __cilkrts_stack_frame that is to be initialized. 436 */ 437CILK_ABI(void) __cilkrts_enter_frame_1(__cilkrts_stack_frame* sf); 438 439/** 440 * __cilkrts_enter_frame_fast is the same as __cilkrts_enter_frame, except it 441 * assumes that the thread has already been bound to a worker. 442 * 443 * @param sf The __cilkrts_stack_frame that is to be initialized. 444 */ 445CILK_ABI(void) __cilkrts_enter_frame_fast(__cilkrts_stack_frame *sf); 446 447/** 448 * __cilkrts_enter_frame_fast_1 is the same as __cilkrts_enter_frame_1, 449 * except it assumes that the thread has already been bound to a worker. 450 * 451 * @param sf The __cilkrts_stack_frame that is to be initialized. 452 */ 453CILK_ABI(void) __cilkrts_enter_frame_fast_1(__cilkrts_stack_frame *sf); 454 455/** 456 * Call leave_frame before leaving a frame, after sync. This function 457 * returns except in a spawn wrapper where the parent has been stolen. 458 * 459 * @param sf The __cilkrts_stack_frame that is to be left. 460 */ 461CILK_ABI(void) __cilkrts_leave_frame(__cilkrts_stack_frame *sf); 462 463/** 464 * Wait for any spawned children of this function to complete before 465 * continuing. This function will only return when the join counter 466 * has gone to 0. Other workers will re-enter the scheduling loop to 467 * attempt to steal additional work. 468 * 469 * @param sf The __cilkrts_stack_frame that is to be synched. 470 */ 471CILK_ABI(void) __cilkrts_sync(__cilkrts_stack_frame *sf); 472 473/** 474 * Called when an exception is escaping a spawn * wrapper. 475 * The stack frame's except_data field is the C++ runtime 476 * exception object. If NULL (temporary workaround) the 477 * currently caught exception should be rethrown. If this 478 * function returns normal exit functions must be called; 479 * undo-detach will have been done. 480 * 481 * @param sf The __cilkrts_stack_frame for the function that 482 * is raising an exception. 483 */ 484CILK_ABI_THROWS(void) 485 __cilkrts_return_exception(__cilkrts_stack_frame *sf); 486 487/** 488 * Called to re-raise an exception. 489 * 490 * @param sf The __cilkrts_stack_frame for the function that 491 * is raising an exception. 492 */ 493CILK_ABI_THROWS(void) __cilkrts_rethrow(__cilkrts_stack_frame *sf); 494 495/** 496 * Called at the beginning of a spawning function to get the worker 497 * that this function is running on. This worker will be used to 498 * initialize the __cilkrts_stack_frame. 499 * 500 * @return The __cilkrts_worker that the function is running on. 501 * @return NULL if this thread is not yet bound to a worker. 502 */ 503CILK_ABI(__cilkrts_worker_ptr) __cilkrts_get_tls_worker(void); 504 505/** 506 * Similar to __cilkrts_get_tls_worker, but assumes that TLS has been 507 * initialized. 508 * 509 * @return The __cilkrts_worker that the function is running on. 510 * @return NULL if this thread is not yet bound to a worker. 511 */ 512CILK_ABI(__cilkrts_worker_ptr) __cilkrts_get_tls_worker_fast(void); 513 514/** 515 * Binds a thread to the runtime by associating a __cilkrts_worker with 516 * it. Called if __cilkrts_get_tls_worker returns NULL. This function will 517 * initialize the runtime the first time it is called. 518 * 519 * This function is versioned by the ABI version number. The runtime 520 * will export all previous versions. This prevents using an application 521 * built with a newer compiler against an old runtime. 522 * 523 * @return The __cilkrts_worker bound to the thread the function is running 524 * on. 525 */ 526CILK_ABI(__cilkrts_worker_ptr) __cilkrts_bind_thread_1(void); 527 528typedef uint32_t cilk32_t; /**< 32-bit unsigned type for cilk_for loop indicies */ 529 530typedef uint64_t cilk64_t; /**< 64-bit unsigned type for cilk_for loop indicies */ 531 532/** 533 * Signature for the lambda function generated for the body of a cilk_for loop 534 * which uses 32-bit indicies 535 */ 536typedef void (*__cilk_abi_f32_t)(void *data, cilk32_t low, cilk32_t high); 537 538/** 539 * Signature for the lambda function generated for the body of a cilk_for lop 540 * which uses 64-bit indicies 541 */ 542typedef void (*__cilk_abi_f64_t)(void *data, cilk64_t low, cilk64_t high); 543 544/** 545 * @brief cilk_for implementation for 32-bit indexes. 546 * 547 * @param body The lambda function for the body of the cilk_for. The lambda 548 * function will be called to execute each grain of work. 549 * @param data Data passed by the compiler into the lambda function. Provides 550 * access to data outside the cilk_for body. 551 * @param count Number of steps in the loop. 552 * @param grain This parameter allows the compiler to pass a value from a 553 * \#pragam(grainsize) statement to allow the user to control the grainsize. If 554 * there isn't a \#pragma(grainsize) immediately preceeding cilk_for loop, Pass 555 * 0 to specify that the runtime should calculate the grainsize using its own 556 * hueristicts. 557 */ 558CILK_ABI_THROWS(void) __cilkrts_cilk_for_32(__cilk_abi_f32_t body, 559 void *data, 560 cilk32_t count, 561 int grain); 562 563/** 564 * @brief cilk_for implementation for 64-bit indexes. 565 * 566 * @copydetails __cilkrts_cilk_for_32 567 */ 568CILK_ABI_THROWS(void) __cilkrts_cilk_for_64(__cilk_abi_f64_t body, 569 void *data, 570 cilk64_t count, 571 int grain); 572 573/** 574 * @brief Allocate memory for variable length arrays. If the frame is 575 * sync'd, the memory will be allocated on the stack, otherwise it will 576 * be allocated from the heap. 577 * 578 * @param sf The __cilkrts_stack_frame for the function allocating the 579 * memory. 580 * @param size The number of bytes requested. 581 * @param distance_from_sp_to_alloca_area ?. 582 * @param align Alignment required. Always >= minimum stack alignment, 583 * >= ptr_size, and always a power of 2. 584 * @param needs_tag Non-zero if the pointer being returned needs to be 585 * tagged 586 * 587 * @return The address of the memory block allocated. 588 */ 589 590CILK_ABI(__cilkrts_void_ptr) 591__cilkrts_stack_alloc(__cilkrts_stack_frame *sf, 592 size_t size, 593 size_t distance_from_sp_to_alloca_area, 594 uint32_t align, 595 uint32_t needs_tag); 596 597/** 598 * @brief Free memory allocated by _cilkrts_stack_alloc() for variable length 599 * arrays. 600 * 601 * @param sf The __cilkrts_stack_frame for the function allocating the 602 * memory. 603 * @param p Pointer to the memory block to be freed. 604 * @param size The number of bytes requested. 605 * @param distance_from_sp_to_alloca_area ?. 606 * @param align Alignment required. Always >= minimum stack alignment, 607 * >= ptr_size, and always a power of 2. 608 * @param know_from_stack Non-zero if the pointer is known to have been 609 * allocated on the stack and has no tag. 610 */ 611CILK_ABI(void) 612__cilkrts_stack_free(__cilkrts_stack_frame *sf, 613 void *p, 614 size_t size, 615 size_t distance_from_sp_to_alloca_area, 616 uint32_t align, 617 uint32_t known_from_stack); 618 619/** 620 * @brief System-dependent code to save floating point control information 621 * to an ABI 1 or higher @c __cilkrts_stack_frame. If possible (and necessary) 622 * the code to save the floating point control information should be inlined. 623 * 624 * Note that this function does *not* save the current floating point 625 * registers. It saves the floating point control words that control 626 * precision and rounding and stuff like that. 627 * 628 * This function will be a noop for architectures that don't have warts 629 * like the floating point control words, or where the information is 630 * already being saved by the setjmp. 631 * 632 * @param sf @c __cilkrts_stack_frame for the frame we're saving the 633 * floating point control information in. 634 */ 635CILK_ABI(void) 636__cilkrts_save_fp_ctrl_state(__cilkrts_stack_frame *sf); 637 638__CILKRTS_END_EXTERN_C 639#endif /* include guard */ 640