github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/runtime/thread.c (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <errno.h> 6 #include <signal.h> 7 #include <sys/time.h> 8 #include <sys/resource.h> 9 10 #include "runtime.h" 11 #include "go-assert.h" 12 13 /* For targets which don't have the required sync support. Really 14 these should be provided by gcc itself. FIXME. */ 15 16 #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) 17 18 /* FIXME(prattmic): see below */ 19 #if 0 20 static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER; 21 #endif 22 23 #endif 24 25 #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 26 27 _Bool 28 __sync_bool_compare_and_swap_4 (uint32*, uint32, uint32) 29 __attribute__ ((visibility ("hidden"))); 30 31 _Bool 32 __sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new) 33 { 34 int i; 35 _Bool ret; 36 37 i = pthread_mutex_lock (&sync_lock); 38 __go_assert (i == 0); 39 40 if (*ptr != old) 41 ret = 0; 42 else 43 { 44 *ptr = new; 45 ret = 1; 46 } 47 48 i = pthread_mutex_unlock (&sync_lock); 49 __go_assert (i == 0); 50 51 return ret; 52 } 53 54 #endif 55 56 #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8 57 58 _Bool 59 __sync_bool_compare_and_swap_8 (uint64*, uint64, uint64) 60 __attribute__ ((visibility ("hidden"))); 61 62 _Bool 63 __sync_bool_compare_and_swap_8 (uint64* ptr, uint64 old, uint64 new) 64 { 65 int i; 66 _Bool ret; 67 68 i = pthread_mutex_lock (&sync_lock); 69 __go_assert (i == 0); 70 71 if (*ptr != old) 72 ret = 0; 73 else 74 { 75 *ptr = new; 76 ret = 1; 77 } 78 79 i = pthread_mutex_unlock (&sync_lock); 80 __go_assert (i == 0); 81 82 return ret; 83 } 84 85 #endif 86 87 #ifndef HAVE_SYNC_FETCH_AND_ADD_4 88 89 uint32 90 __sync_fetch_and_add_4 (uint32*, uint32) 91 __attribute__ ((visibility ("hidden"))); 92 93 uint32 94 __sync_fetch_and_add_4 (uint32* ptr, uint32 add) 95 { 96 int i; 97 uint32 ret; 98 99 i = pthread_mutex_lock (&sync_lock); 100 __go_assert (i == 0); 101 102 ret = *ptr; 103 *ptr += add; 104 105 i = pthread_mutex_unlock (&sync_lock); 106 __go_assert (i == 0); 107 108 return ret; 109 } 110 111 #endif 112 113 #ifndef HAVE_SYNC_ADD_AND_FETCH_8 114 115 /* 116 * FIXME(prattmic): LLVM thinks this is overriding a builtin, even though it 117 * doesn't provide this builtin. 118 */ 119 #if 0 120 long long 121 __sync_add_and_fetch_8 (volatile long long*, long long, ...) 122 __attribute__ ((visibility ("hidden"))); 123 124 long long 125 __sync_add_and_fetch_8 (volatile long long* ptr, long long add, ...) 126 { 127 int i; 128 uint64 ret; 129 130 i = pthread_mutex_lock (&sync_lock); 131 __go_assert (i == 0); 132 133 *ptr += add; 134 ret = *ptr; 135 136 i = pthread_mutex_unlock (&sync_lock); 137 __go_assert (i == 0); 138 139 return ret; 140 } 141 #endif 142 143 #endif 144 145 uintptr 146 runtime_memlimit(void) 147 { 148 struct rlimit rl; 149 uintptr used; 150 151 if(getrlimit(RLIMIT_AS, &rl) != 0) 152 return 0; 153 if(rl.rlim_cur >= 0x7fffffff) 154 return 0; 155 156 // Estimate our VM footprint excluding the heap. 157 // Not an exact science: use size of binary plus 158 // some room for thread stacks. 159 used = (64<<20); 160 if(used >= rl.rlim_cur) 161 return 0; 162 163 // If there's not at least 16 MB left, we're probably 164 // not going to be able to do much. Treat as no limit. 165 rl.rlim_cur -= used; 166 if(rl.rlim_cur < (16<<20)) 167 return 0; 168 169 return rl.rlim_cur - used; 170 }