2010-12-03 05:34:57 +01:00
|
|
|
// 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.
|
|
|
|
|
2011-03-09 07:31:37 +01:00
|
|
|
#include <errno.h>
|
2011-11-28 06:45:49 +01:00
|
|
|
#include <signal.h>
|
2012-03-06 18:57:23 +01:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
2011-11-28 06:45:49 +01:00
|
|
|
|
2010-12-03 05:34:57 +01:00
|
|
|
#include "runtime.h"
|
2011-02-01 21:15:13 +01:00
|
|
|
#include "go-assert.h"
|
2010-12-03 05:34:57 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
/* For targets which don't have the required sync support. Really
|
|
|
|
these should be provided by gcc itself. FIXME. */
|
2010-12-17 07:42:06 +01:00
|
|
|
|
2012-02-12 07:23:08 +01:00
|
|
|
#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)
|
2010-12-17 07:42:06 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
|
2010-12-03 05:34:57 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
#endif
|
2010-12-03 05:34:57 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
|
2010-12-17 07:42:06 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
_Bool
|
|
|
|
__sync_bool_compare_and_swap_4 (uint32*, uint32, uint32)
|
|
|
|
__attribute__ ((visibility ("hidden")));
|
2010-12-03 05:34:57 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
_Bool
|
|
|
|
__sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new)
|
2010-12-03 05:34:57 +01:00
|
|
|
{
|
2011-11-22 21:24:44 +01:00
|
|
|
int i;
|
|
|
|
_Bool ret;
|
2010-12-03 05:34:57 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
i = pthread_mutex_lock (&sync_lock);
|
|
|
|
__go_assert (i == 0);
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
if (*ptr != old)
|
|
|
|
ret = 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*ptr = new;
|
|
|
|
ret = 1;
|
|
|
|
}
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
i = pthread_mutex_unlock (&sync_lock);
|
|
|
|
__go_assert (i == 0);
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
return ret;
|
|
|
|
}
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
#endif
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2012-02-12 07:23:08 +01:00
|
|
|
#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
|
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
#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)
|
2011-02-01 21:15:13 +01:00
|
|
|
{
|
|
|
|
int i;
|
2011-11-22 21:24:44 +01:00
|
|
|
uint32 ret;
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
i = pthread_mutex_lock (&sync_lock);
|
|
|
|
__go_assert (i == 0);
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
ret = *ptr;
|
|
|
|
*ptr += add;
|
2011-02-01 21:15:13 +01:00
|
|
|
|
2011-11-22 21:24:44 +01:00
|
|
|
i = pthread_mutex_unlock (&sync_lock);
|
|
|
|
__go_assert (i == 0);
|
2011-02-01 21:15:13 +01:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2011-11-28 06:45:49 +01:00
|
|
|
|
2012-02-12 07:23:08 +01:00
|
|
|
#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
|
|
|
|
|
2011-11-28 06:45:49 +01:00
|
|
|
// Called to initialize a new m (including the bootstrap m).
|
|
|
|
void
|
|
|
|
runtime_minit(void)
|
|
|
|
{
|
|
|
|
byte* stack;
|
|
|
|
size_t stacksize;
|
|
|
|
stack_t ss;
|
2012-03-06 18:57:23 +01:00
|
|
|
sigset_t sigs;
|
2011-11-28 06:45:49 +01:00
|
|
|
|
|
|
|
// Initialize signal handling.
|
|
|
|
runtime_m()->gsignal = runtime_malg(32*1024, &stack, &stacksize); // OS X wants >=8K, Linux >=2K
|
|
|
|
ss.ss_sp = stack;
|
|
|
|
ss.ss_flags = 0;
|
|
|
|
ss.ss_size = stacksize;
|
|
|
|
if(sigaltstack(&ss, nil) < 0)
|
|
|
|
*(int *)0xf1 = 0xf1;
|
2012-03-06 18:57:23 +01:00
|
|
|
if (sigemptyset(&sigs) != 0)
|
|
|
|
runtime_throw("sigemptyset");
|
|
|
|
sigprocmask(SIG_SETMASK, &sigs, nil);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2011-11-28 06:45:49 +01:00
|
|
|
}
|