// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include #include #include #include #include "runtime.h" #include "go-assert.h" /* For targets which don't have the required sync support. Really these should be provided by gcc itself. FIXME. */ #if !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4) || !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8) || !defined (HAVE_SYNC_FETCH_AND_ADD_4) || !defined (HAVE_SYNC_ADD_AND_FETCH_8) static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER; #endif #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 _Bool __sync_bool_compare_and_swap_4 (uint32*, uint32, uint32) __attribute__ ((visibility ("hidden"))); _Bool __sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new) { int i; _Bool ret; i = pthread_mutex_lock (&sync_lock); __go_assert (i == 0); if (*ptr != old) ret = 0; else { *ptr = new; ret = 1; } i = pthread_mutex_unlock (&sync_lock); __go_assert (i == 0); return ret; } #endif #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8 _Bool __sync_bool_compare_and_swap_8 (uint64*, uint64, uint64) __attribute__ ((visibility ("hidden"))); _Bool __sync_bool_compare_and_swap_8 (uint64* ptr, uint64 old, uint64 new) { int i; _Bool ret; i = pthread_mutex_lock (&sync_lock); __go_assert (i == 0); if (*ptr != old) ret = 0; else { *ptr = new; ret = 1; } i = pthread_mutex_unlock (&sync_lock); __go_assert (i == 0); return ret; } #endif #ifndef HAVE_SYNC_FETCH_AND_ADD_4 uint32 __sync_fetch_and_add_4 (uint32*, uint32) __attribute__ ((visibility ("hidden"))); uint32 __sync_fetch_and_add_4 (uint32* ptr, uint32 add) { int i; uint32 ret; i = pthread_mutex_lock (&sync_lock); __go_assert (i == 0); ret = *ptr; *ptr += add; i = pthread_mutex_unlock (&sync_lock); __go_assert (i == 0); return ret; } #endif #ifndef HAVE_SYNC_ADD_AND_FETCH_8 uint64 __sync_add_and_fetch_8 (uint64*, uint64) __attribute__ ((visibility ("hidden"))); uint64 __sync_add_and_fetch_8 (uint64* ptr, uint64 add) { int i; uint64 ret; i = pthread_mutex_lock (&sync_lock); __go_assert (i == 0); *ptr += add; ret = *ptr; i = pthread_mutex_unlock (&sync_lock); __go_assert (i == 0); return ret; } #endif uintptr runtime_memlimit(void) { struct rlimit rl; uintptr used; if(getrlimit(RLIMIT_AS, &rl) != 0) return 0; if(rl.rlim_cur >= 0x7fffffff) return 0; // Estimate our VM footprint excluding the heap. // Not an exact science: use size of binary plus // some room for thread stacks. used = (64<<20); if(used >= rl.rlim_cur) return 0; // If there's not at least 16 MB left, we're probably // not going to be able to do much. Treat as no limit. rl.rlim_cur -= used; if(rl.rlim_cur < (16<<20)) return 0; return rl.rlim_cur - used; }