os-unix.c 16.3 KB
Newer Older
1 2 3 4
/* os-unix.c                  -*-C-*-
 *
 *************************************************************************
 *
Hansang Bae's avatar
Hansang Bae committed
5
 *  Copyright (C) 2009-2015, Intel Corporation
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *  All rights reserved.
 *  
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in
 *      the documentation and/or other materials provided with the
 *      distribution.
 *    * Neither the name of Intel Corporation nor the names of its
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *  
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 *  WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
34 35 36 37 38 39 40 41 42 43 44 45 46 47
 *  
 *  *********************************************************************
 *  
 *  PLEASE NOTE: This file is a downstream copy of a file mainitained in
 *  a repository at cilkplus.org. Changes made to this file that are not
 *  submitted through the contribution process detailed at
 *  http://www.cilkplus.org/submit-cilk-contribution will be lost the next
 *  time that a new version is released. Changes only submitted to the
 *  GNU compiler collection or posted to the git repository at
 *  https://bitbucket.org/intelcilkplusruntime/itnel-cilk-runtime.git are
 *  not tracked.
 *  
 *  We welcome your contributions to this open source project. Thank you
 *  for your assistance in helping us improve Cilk Plus.
48 49 50 51
 **************************************************************************/

#include "os.h"
#include "bug.h"
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
52
#include "cilk_malloc.h"
53 54 55 56 57
#include <internal/abi.h>

#if defined __linux__
#   include <sys/sysinfo.h>
#   include <sys/syscall.h>
Hansang Bae's avatar
Hansang Bae committed
58

59 60 61
#elif defined __APPLE__
#   include <sys/sysctl.h>
    // Uses sysconf(_SC_NPROCESSORS_ONLN) in verbose output
Hansang Bae's avatar
Hansang Bae committed
62

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
63 64 65
#elif defined  __VXWORKS__
#   include <vxWorks.h>   
#   include <vxCpuLib.h>   
Hansang Bae's avatar
Hansang Bae committed
66 67
#   include <taskLib.h>
   
Barry Tannenbaum's avatar
Barry Tannenbaum committed
68 69 70
// Solaris
#elif defined __sun__ && defined __svr4__
#   include <sched.h>
Hansang Bae's avatar
Hansang Bae committed
71 72 73 74 75 76 77 78

// OSes we know about which don't require any additional files
#elif defined __CYGWIN__ || \
      defined __DragonFly__ || \
      defined __FreeBSD__ || \
      defined __GNU__
// No additional include files

79
#else
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
80
#   error "Unsupported OS"
81 82 83 84 85 86 87 88 89 90 91 92
#endif

#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>


barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
93

94 95 96 97 98 99 100 101 102 103 104 105
// /* Thread-local storage */
// #ifdef _WIN32
// typedef unsigned cilkos_tls_key_t;
// #else
// typedef pthread_key_t cilkos_tls_key_t;
// #endif
// cilkos_tls_key_t cilkos_allocate_tls_key();
// void cilkos_set_tls_pointer(cilkos_tls_key_t key, void* ptr);
// void* cilkos_get_tls_pointer(cilkos_tls_key_t key);

#if !defined CILK_WORKER_TLS
static int cilk_keys_defined;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
106 107 108 109 110 111
static pthread_key_t worker_key, pedigree_leaf_key, tbb_interop_key;

#if SUPPORT_GET_CURRENT_FIBER > 0
static pthread_key_t fiber_key;
#endif

112 113
static void *serial_worker;

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
114 115 116 117 118 119 120 121 122 123 124

// This destructor is called when a pthread dies to deallocate the
// pedigree node.
static void __cilkrts_pedigree_leaf_destructor(void* pedigree_tls_ptr)
{
    __cilkrts_pedigree* pedigree_tls
	= (__cilkrts_pedigree*)pedigree_tls_ptr;
    if (pedigree_tls) {
        // Assert that we have either one or two nodes
        // left in the pedigree chain.
        // If we have more, then something is going wrong...
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
125
        CILK_ASSERT(!pedigree_tls->parent || !pedigree_tls->parent->parent);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
126 127 128 129
	__cilkrts_free(pedigree_tls);
    }
}

130 131 132 133 134 135 136 137
void __cilkrts_init_tls_variables(void)
{
    int status;
    /* This will be called once in serial execution before any
       Cilk parallelism so we do not need to worry about races
       on cilk_keys_defined. */
    if (cilk_keys_defined)
        return;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
138
    status = pthread_key_create(&worker_key, NULL);
139
    CILK_ASSERT (status == 0);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
140 141 142
    status = pthread_key_create(&pedigree_leaf_key,
				__cilkrts_pedigree_leaf_destructor);
    CILK_ASSERT (status == 0);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
143 144 145 146 147 148 149
    status = pthread_key_create(&tbb_interop_key, NULL);
    CILK_ASSERT (status == 0);

#if SUPPORT_GET_CURRENT_FIBER > 0    
    status = pthread_key_create(&fiber_key, NULL);
    CILK_ASSERT (status == 0);
#endif
150 151 152 153
    cilk_keys_defined = 1;
    return;
}

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
154 155 156 157 158 159 160
COMMON_SYSDEP
void* cilkos_get_current_thread_id(void)
{
    return (void*)pthread_self();
}


161 162 163 164
CILK_ABI_WORKER_PTR __cilkrts_get_tls_worker()
{
    if (__builtin_expect(cilk_keys_defined, 1))
        return (__cilkrts_worker *)pthread_getspecific(worker_key);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
165
    else 
166
        return serial_worker;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
167
    
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
}

CILK_ABI_WORKER_PTR __cilkrts_get_tls_worker_fast()
{
  return (__cilkrts_worker *)pthread_getspecific(worker_key);
}

COMMON_SYSDEP
__cilk_tbb_stack_op_thunk *__cilkrts_get_tls_tbb_interop(void)
{
    if (__builtin_expect(cilk_keys_defined, 1))
        return (__cilk_tbb_stack_op_thunk *)
            pthread_getspecific(tbb_interop_key);
    else
        return 0;
}

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
// This counter should be updated atomically.
static int __cilkrts_global_pedigree_tls_counter = -1;

COMMON_SYSDEP
__cilkrts_pedigree *__cilkrts_get_tls_pedigree_leaf(int create_new)
{
    __cilkrts_pedigree *pedigree_tls;    
    if (__builtin_expect(cilk_keys_defined, 1)) {
        pedigree_tls =
            (struct __cilkrts_pedigree *)pthread_getspecific(pedigree_leaf_key);
    }
    else {
        return 0;
    }
    
    if (!pedigree_tls && create_new) {
        // This call creates two nodes, X and Y.
        // X == pedigree_tls[0] is the leaf node, which gets copied
        // in and out of a user worker w when w binds and unbinds.
        // Y == pedigree_tls[1] is the root node,
        // which is a constant node that represents the user worker
        // thread w.
	pedigree_tls = (__cilkrts_pedigree*)
	    __cilkrts_malloc(2 * sizeof(__cilkrts_pedigree));

        // This call sets the TLS pointer to the new node.
	__cilkrts_set_tls_pedigree_leaf(pedigree_tls);
        
        pedigree_tls[0].rank = 0;
        pedigree_tls[0].parent = &pedigree_tls[1];

        // Create Y, whose rank begins as the global counter value.
        pedigree_tls[1].rank =
            __sync_add_and_fetch(&__cilkrts_global_pedigree_tls_counter, 1);

        pedigree_tls[1].parent = NULL;
        CILK_ASSERT(pedigree_tls[1].rank != -1);
    }
    return pedigree_tls;
}

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
226 227 228 229 230 231 232 233 234 235 236
#if SUPPORT_GET_CURRENT_FIBER > 0
COMMON_SYSDEP
cilk_fiber_sysdep* cilkos_get_tls_cilk_fiber(void)
{
    if (__builtin_expect(cilk_keys_defined, 1))
        return (cilk_fiber_sysdep *)pthread_getspecific(fiber_key);
    else
        return NULL;
}
#endif

237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
COMMON_SYSDEP
void __cilkrts_set_tls_worker(__cilkrts_worker *w)
{
    if (__builtin_expect(cilk_keys_defined, 1)) {
        int status;
        status = pthread_setspecific(worker_key, w);
        CILK_ASSERT (status == 0);
        return;
    }
    else
    {
        serial_worker = w;
    }
}

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
252 253
COMMON_SYSDEP
void __cilkrts_set_tls_tbb_interop(__cilk_tbb_stack_op_thunk *t)
254 255 256
{
    if (__builtin_expect(cilk_keys_defined, 1)) {
        int status;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
257
        status = pthread_setspecific(tbb_interop_key, t);
258 259 260 261 262 263 264
        CILK_ASSERT (status == 0);
        return;
    }
    abort();
}

COMMON_SYSDEP
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
265
void __cilkrts_set_tls_pedigree_leaf(__cilkrts_pedigree* pedigree_leaf)
266 267 268
{
    if (__builtin_expect(cilk_keys_defined, 1)) {
        int status;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
269
        status = pthread_setspecific(pedigree_leaf_key, pedigree_leaf);
270 271 272 273 274
        CILK_ASSERT (status == 0);
        return;
    }
    abort();
}
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
275

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
276
#if SUPPORT_GET_CURRENT_FIBER > 0
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
277
COMMON_SYSDEP
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
278
void cilkos_set_tls_cilk_fiber(cilk_fiber_sysdep* fiber)
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
279 280 281
{
    if (__builtin_expect(cilk_keys_defined, 1)) {
        int status;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
282
        status = pthread_setspecific(fiber_key, fiber);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
283 284 285 286 287
        CILK_ASSERT (status == 0);
        return;
    }
    abort();
}
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
288
#endif
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
289

290 291 292 293 294 295
#else
void __cilkrts_init_tls_variables(void)
{
}
#endif

Barry Tannenbaum's avatar
Barry Tannenbaum committed
296
#if defined (__linux__) && ! defined(__ANDROID__)
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
/*
 * Get the thread id, rather than the pid. In the case of MIC offload, it's
 * possible that we have multiple threads entering Cilk, and each has a
 * different affinity.
 */
static pid_t linux_gettid(void)
{
    return syscall(SYS_gettid);
}

/*
 * On Linux we look at the thread affinity mask and restrict ourself to one
 * thread for each of the hardware contexts to which we are bound.
 * Therefore if user does
 * % taskset 0-1 cilkProgram
 *       # restrict execution to hardware contexts zero and one
 * the Cilk program will only use two threads even if it is running on a
 * machine that has 32 hardware contexts.
 * This is the right thing to do, because the threads are restricted to two
 * hardware contexts by the affinity mask set by taskset, and if we were to
 * create extra threads they would simply oversubscribe the hardware resources
 * we can use.
 * This is particularly important on MIC in offload mode, where the affinity
 * mask is set by the offload library to force the offload code away from
 * cores that have offload support threads running on them.
 */
Barry Tannenbaum's avatar
Barry Tannenbaum committed
323
static int linux_get_affinity_count ()
324
{
Barry Tannenbaum's avatar
Barry Tannenbaum committed
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
    long system_cores = sysconf(_SC_NPROCESSORS_ONLN);
    int affinity_cores = 0;

#if defined HAVE_PTHREAD_AFFINITY_NP

#if defined (CPU_ALLOC_SIZE) && ! defined(DONT_USE_CPU_ALLOC_SIZE)
    // Statically allocated cpu_set_t's max out at 1024 cores.  If
    // CPU_ALLOC_SIZE is available, use it to support large numbers of cores
    size_t cpusetsize = CPU_ALLOC_SIZE(system_cores);
    cpu_set_t *process_mask = (cpu_set_t *)__cilkrts_malloc(cpusetsize);

    // Get the affinity mask for this thread
    int err = pthread_getaffinity_np(pthread_self(),
                                     cpusetsize,
                                     process_mask);

    // Count the available cores.
    if (0 == err)
        affinity_cores = CPU_COUNT_S(cpusetsize, process_mask);

    __cilkrts_free(process_mask);

#else
    // CPU_ALLOC_SIZE isn't available, or this is the Intel compiler build
    // and we have to support RHEL5.  Use a statically allocated cpu_set_t

351 352 353
    cpu_set_t process_mask;

    // Extract the thread affinity mask
Barry Tannenbaum's avatar
Barry Tannenbaum committed
354 355 356
    int err = pthread_getaffinity_np(pthread_self(),
                                     sizeof(process_mask),
                                     &process_mask);
357

Barry Tannenbaum's avatar
Barry Tannenbaum committed
358
    if (0 == err)
359
    {
Barry Tannenbaum's avatar
Barry Tannenbaum committed
360 361 362 363 364 365 366
        // We have extracted the mask OK, so now we can count the number of
        // threads in it.  This is linear in the maximum number of CPUs
        // available, We could do a logarithmic version, if we assume the
        // format of the mask, but it's not really worth it. We only call
        // this at thread startup anyway.
        int i;
        for (i = 0; i < CPU_SETSIZE; i++)
367
        {
Barry Tannenbaum's avatar
Barry Tannenbaum committed
368 369 370 371
            if (CPU_ISSET(i, &process_mask))
            {
                affinity_cores++;
            }
372 373
        }
    }
Barry Tannenbaum's avatar
Barry Tannenbaum committed
374 375 376 377 378 379 380 381 382 383
#endif  // CPU_ALLOC_SIZE
#endif  //  ! defined HAVE_PTHREAD_AFFINITY_NP

    // If we've got a count of cores this thread is supposed to use, that's
    // the number or cores we'll use.  Otherwise, default to the number of
    // cores on the system.
    if (0 == affinity_cores)
        return system_cores;
    else
        return affinity_cores;
384
}
Barry Tannenbaum's avatar
Barry Tannenbaum committed
385
#endif  //  defined (__linux__) && ! defined(__ANDROID__)
386 387 388 389 390 391 392 393 394 395

/*
 * __cilkrts_hardware_cpu_count
 *
 * Returns the number of available CPUs on this hardware.  This is architecture-
 * specific. 
 */

COMMON_SYSDEP int __cilkrts_hardware_cpu_count(void)
{
396 397
#if defined __ANDROID__  || \
    defined __CYGWIN__   || \
Hansang Bae's avatar
Hansang Bae committed
398 399
    defined __DragonFly__  || \
    defined __FreeBSD__  || \
400 401
    (defined(__sun__) && defined(__svr4__))
    return (int)sysconf(_SC_NPROCESSORS_ONLN);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
402 403 404
#elif defined __MIC__
    /// HACK: Usually, the 3rd and 4th hyperthreads are not beneficial
    /// on KNC.  Also, ignore the last core.
405 406
    int count = (int)sysconf (_SC_NPROCESSORS_ONLN);
    return count/2 - 2;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
407
#elif defined __linux__
Barry Tannenbaum's avatar
Barry Tannenbaum committed
408
    return linux_get_affinity_count();
409
#elif defined __APPLE__
410
    int count;
411
    size_t len = sizeof count;
412 413
    int status = sysctlbyname("hw.logicalcpu", &count, &len, 0, 0);
    assert(0 == status);
414 415

    return count;
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
416
#elif defined  __VXWORKS__
417
    return __builtin_popcount(vxCpuEnabledGet());
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
418
#else
Hansang Bae's avatar
Hansang Bae committed
419
#error "Unsupported architecture"
420 421 422 423 424
#endif
}

COMMON_SYSDEP void __cilkrts_sleep(void)
{
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
425
#ifdef __VXWORKS__
Barry Tannenbaum's avatar
Barry Tannenbaum committed
426
    taskDelay(1);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
427
#else			
428
    usleep(1);
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
429
#endif	
430 431 432 433
}

COMMON_SYSDEP void __cilkrts_yield(void)
{
Hansang Bae's avatar
Hansang Bae committed
434 435 436 437 438 439
#if defined(__ANDROID__)  || \
    defined(__APPLE__)    || \
    defined(__FreeBSD__)  || \
    defined(__VXWORKS__)  || \
    (defined(__sun__) && defined(__svr4__))
    // Call sched_yield to yield quantum.  I'm not sure why we
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
440
    // don't do this on Linux also.
441
    sched_yield();
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
442 443 444 445 446 447 448
#elif defined(__MIC__)
    // On MIC, pthread_yield() really trashes things.  Arch's measurements
    // showed that calling _mm_delay_32() (or doing nothing) was a better
    // option.  Delaying 1024 clock cycles is a reasonable compromise between
    // giving up the processor and latency starting up when work becomes
    // available
    _mm_delay_32(1024);
Hansang Bae's avatar
Hansang Bae committed
449
#elif defined(__linux__)
barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
450 451
    // On Linux, call pthread_yield (which in turn will call sched_yield)
    // to yield quantum.
452
    pthread_yield();
Hansang Bae's avatar
Hansang Bae committed
453 454
#else
# error "Unsupported architecture"
455 456 457 458 459 460 461 462 463 464 465 466
#endif
}

COMMON_SYSDEP __STDNS size_t cilkos_getenv(char* value, __STDNS size_t vallen,
                                           const char* varname)
{
    CILK_ASSERT(value);
    CILK_ASSERT(varname);

    const char* envstr = getenv(varname);
    if (envstr)
    {
Hansang Bae's avatar
Hansang Bae committed
467
        size_t len = cilk_strlen(envstr);
468 469
        if (len > vallen - 1)
            return len + 1;
Hansang Bae's avatar
Hansang Bae committed
470
        cilk_strcpy_s(value, vallen, envstr);
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
        return len;
    }
    else
    {
        value[0] = '\0';
        return 0;
    }
}

/*
 * Unrecoverable error: Print an error message and abort execution.
 */
COMMON_SYSDEP void cilkos_error(const char *fmt, ...)
{
    va_list l;
    fflush(NULL);
    fprintf(stderr, "Cilk error: ");
    va_start(l, fmt);
    vfprintf(stderr, fmt, l);
    va_end(l);
    fprintf(stderr, "Exiting.\n");
    fflush(stderr);

    abort();
}

/*
 * Print a warning message and return.
 */
COMMON_SYSDEP void cilkos_warning(const char *fmt, ...)
{
    va_list l;
    fflush(NULL);
    fprintf(stderr, "Cilk warning: ");
    va_start(l, fmt);
    vfprintf(stderr, fmt, l);
    va_end(l);
    fflush(stderr);
}

Hansang Bae's avatar
Hansang Bae committed
511 512 513 514 515 516 517 518 519 520 521 522 523
#ifdef __VXWORKS__
#ifdef _WRS_KERNEL
void cilkStart()
{
    __cilkrts_init_tls_variables();
}
#else
_WRS_CONSTRUCTOR(cilkInit, 100)
{
    __cilkrts_init_tls_variables();
}
#endif
#else
524 525 526 527 528
static void __attribute__((constructor)) init_once()
{
    /*__cilkrts_debugger_notification_internal(CILK_DB_RUNTIME_LOADED);*/
    __cilkrts_init_tls_variables();
}
Hansang Bae's avatar
Hansang Bae committed
529
#endif
530

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558

#define PAGE 4096
#define CILK_MIN_STACK_SIZE (4*PAGE)
// Default size for the stacks that we create in Cilk for Unix.
#define CILK_DEFAULT_STACK_SIZE 0x100000

/*
 * Convert the user's specified stack size into a "reasonable" value
 * for this OS.
 */
size_t cilkos_validate_stack_size(size_t specified_stack_size) {
    // Convert any negative value to the default.
    if (specified_stack_size == 0) {
        CILK_ASSERT((CILK_DEFAULT_STACK_SIZE % PAGE) == 0);
        return CILK_DEFAULT_STACK_SIZE;
    }
    // Round values in between 0 and CILK_MIN_STACK_SIZE up to
    // CILK_MIN_STACK_SIZE.
    if (specified_stack_size <= CILK_MIN_STACK_SIZE) {
        return CILK_MIN_STACK_SIZE;
    }
    if ((specified_stack_size % PAGE) > 0) {
        // Round the user's stack size value up to nearest page boundary.
        return (PAGE * (1 + specified_stack_size / PAGE));
    }
    return specified_stack_size;
}

barry.m.tannenbaum's avatar
barry.m.tannenbaum committed
559 560 561 562 563
long cilkos_atomic_add(volatile long* p, long x)
{
    return __sync_add_and_fetch(p, x);
}

564
/* End os-unix.c */