1 /* Copyright (C) 2003-2014 Free Software Foundation, Inc.
2 This file is part of the UPC runtime Library.
3 Written by Gary Funck <gary@intrepid.com>
4 and Nenad Vukicevic <nenad@intrepid.com>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2, or (at
9 your option) any later version.
11 This library is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this library; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
21 As a special exception, if you link this library with files
22 compiled with a GNU compiler to produce an executable, this does
23 not cause the resulting executable to be covered by the GNU General
24 Public License. This exception does not however invalidate any
25 other reasons why the executable file might be covered by the GNU
26 General Public License. */
28 #include "upc_config.h"
29 #include "upc_sysdep.h"
35 #ifndef _SC_NPROCESSORS_ONLN
36 #define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
45 __upc_num_cpus
= (int) sysconf (_SC_NPROCESSORS_ONLN
);
47 /* Make sure that this main process is the process group leader */
48 if (getpgrp() != getpid())
50 if (setpgid(0, 0) == -1)
51 { perror("setpgid"); exit (2); }
55 char *__upc_strsignal (sig
)
58 static char sigbuf
[64];
60 char **sys_siglist
= _sys_siglist
;
61 const int nsig
= _sys_nsig
;
63 extern const char * const sys_siglist
[];
64 const int nsig
= NSIG
;
66 if (sig
> 0 && sig
< nsig
)
67 return (char *)sys_siglist
[sig
];
69 return (sprintf (sigbuf
, "signal number %d", sig
), sigbuf
);
72 #ifndef __upc_atomic_cas
73 /* If a builtin implementation of __upc_atomic_cas was found,
74 then the symbol will be defined as a pre-processor macro.
75 Otherwise, implement the function out-of-line. */
78 __upc_atomic_cas (os_atomic_p ptr
, os_atomic_t old
, os_atomic_t
new)
80 upc_info_p u
= __upc_info
;
81 return uscas ((void *)ptr
, old
, new, (usptr_t
*)u
->runtime_heap
);
85 #define LOCK_PREFIX "lock ; "
88 __upc_atomic_cas (os_atomic_p ptr
, os_atomic_t old
, os_atomic_t
new)
91 __asm__
__volatile__(LOCK_PREFIX
"cmpxchgl %1,%2"
93 : "q"(new), "m"(*ptr
), "0"(old
)
99 #define LOCK_PREFIX "lock ; "
102 __upc_atomic_cas (os_atomic_p ptr
, os_atomic_t old
, os_atomic_t
new)
105 __asm__
__volatile__(LOCK_PREFIX
"cmpxchgl %1,%2"
107 : "q"(new), "m"(*ptr
), "0"(old
)
114 #include <linux/types.h>
115 #include <asm/intrinsics.h>
118 __upc_atomic_cas (os_atomic_p ptr
, os_atomic_t old
, os_atomic_t
new)
121 prev
= cmpxchg (ptr
, old
, new);
125 #error "__upc_atomic_cas not implemented on this target"
127 #endif /* ! __upc_atomic_cas */
130 __upc_atomic_get_bit (os_atomic_p bits
, int bitnum
)
132 os_atomic_t
*word_ptr
= bits
+ (bitnum
/ OS_BITS_PER_ATOMIC_WORD
);
133 os_atomic_t bit
= (1 << (bitnum
% OS_BITS_PER_ATOMIC_WORD
));
134 os_atomic_t word
= *word_ptr
;
136 return (word
& bit
) != 0;
140 __upc_atomic_set_bit (os_atomic_p bits
, int bitnum
)
142 os_atomic_t
*word
= bits
+ (bitnum
/ OS_BITS_PER_ATOMIC_WORD
);
143 os_atomic_t bit
= (1 << (bitnum
% OS_BITS_PER_ATOMIC_WORD
));
144 os_atomic_t old_val
, new_val
;
148 new_val
= old_val
| bit
;
150 while (!__upc_atomic_cas (word
, old_val
, new_val
));
154 __upc_create_runtime_heap (size_t ARG_UNUSED (max_size
),
155 const char **ARG_UNUSED (err_msg
))
159 /* Create the shared arena. */
160 (void) usconfig (CONF_INITSIZE
, max_size
);
161 heap
= (os_heap_p
) usinit (DEV_ZERO
);
163 { *err_msg
= strerror(errno
); return 0; }
165 /* On platforms other than SGI/Irix we don't
166 need a heap, because mmap() will work well
167 for the limited number of data structures
168 allocated during runtime initialization. */
175 __upc_runtime_alloc (size_t size
, os_heap_p
*ARG_UNUSED (heap
),
176 const char **err_msg
)
180 alloc
= (void *) usmalloc (size
, (usptr_t
*)*heap
);
182 { *err_msg
= strerror(errno
); return 0; }
184 alloc
= mmap ((void *) 0, size
,
185 PROT_READ
| PROT_WRITE
,
186 MAP_SHARED
| MAP_ANONYMOUS
, 0, OFFSET_ZERO
);
187 if (!alloc
|| alloc
== MAP_ERROR
)
188 { *err_msg
= strerror(errno
); return 0; }
194 __upc_init_lock (lock
)
199 upc_info_p u
= __upc_info
;
201 __upc_fatal ("UPC runtime not initialized");
202 *lock
= (os_lock_t
) usnewlock ((usptr_t
*) u
->runtime_heap
);
204 { perror ("__upc_init_lock"); abort (); }
212 __upc_acquire_lock (lock
)
216 __upc_fatal ("NULL shared pointer passed to UPC lock operation");
220 status
= ussetlock(*lock
);
222 __upc_fatal ("upc_lock() could not acquire lock");
224 { perror ("upc_acquire_lock"); abort (); }
227 __upc_spin_until (__upc_atomic_cas ((os_atomic_p
) lock
, 0, 1));
233 __upc_try_acquire_lock (lock
)
238 __upc_fatal ("NULL shared pointer passed to UPC lock operation");
240 status
= uscsetlock(*lock
, 0);
242 { perror ("upc_try_acquire_lock"); abort (); }
244 status
= __upc_atomic_cas ((os_atomic_p
) lock
, 0, 1);
252 __upc_release_lock (lock
)
256 __upc_fatal ("NULL shared pointer passed to UPC lock operation");
261 status
= usunsetlock(*lock
);
263 __upc_fatal ("upc_unlock() could not release lock");
265 { perror ("upc_unlock"); abort (); }
268 *((os_atomic_p
) lock
) = 0;
272 /* Given a "tag" (a relative filename ending in XXXXXX),
273 create a temporary file using the tag.
274 Return a file descriptor associated with the newly
275 created temporary file.
276 [see: http://www.linux.com/howtos/Secure-Programs-HOWTO/avoid-race.shtml] */
279 __upc_create_temp_file (const char *tag
, char *tmp_fname
,
280 const char **err_msg
)
282 const char *tmpdir
= NULL
;
285 if ((getuid () == geteuid ()) && (getgid () == getegid ()))
287 tmpdir
= getenv ("TMPDIR");
289 tmpdir
= getenv ("TMP");
293 sprintf (tmp_fname
, "%s/%s", tmpdir
, tag
);
294 /* Create file with restrictive permissions */
295 old_mode
= umask (077);
296 fd
= mkstemp (tmp_fname
);
297 (void) umask (old_mode
);
299 *err_msg
= "Couldn't open temporary file";
303 /* Create a file that will be used as the backing store
304 for the UPC program's global shared memory. Return
305 a file descriptor that can subsequently be used
306 to mmap() the file. If an error is encountered,
307 fd will be set to -1, and err_msg will contain
308 a descriptive error message. */
310 __upc_create_global_mem_file (char *tmp_fname
, const char **err_msg
)
313 char fname_template
[30];
314 sprintf (fname_template
, "upc_shmem.%d.XXXXXX", (int)getpid());
315 fd
= __upc_create_temp_file (fname_template
, tmp_fname
, err_msg
);