1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef prunixos_h___
7 #define prunixos_h___
8 
9 /*
10  * If FD_SETSIZE is not defined on the command line, set the default value
11  * before include select.h
12  */
13 /*
14  * Linux: FD_SETSIZE is defined in /usr/include/sys/select.h and should
15  * not be redefined.
16  */
17 #if !defined(LINUX) && !defined(__GNU__) && !defined(__GLIBC__) \
18     && !defined(DARWIN)
19 #ifndef FD_SETSIZE
20 #define FD_SETSIZE  4096
21 #endif
22 #endif
23 
24 #include <unistd.h>
25 #include <stddef.h>
26 #include <sys/stat.h>
27 #include <dirent.h>
28 #include <errno.h>
29 
30 #include "prio.h"
31 #include "prmem.h"
32 #include "prclist.h"
33 
34 /*
35  * For select(), fd_set, and struct timeval.
36  *
37  * In The Single UNIX(R) Specification, Version 2,
38  * the header file for select() is <sys/time.h>.
39  * In Version 3, the header file for select() is
40  * changed to <sys/select.h>.
41  *
42  * fd_set is defined in <sys/types.h>.  Usually
43  * <sys/time.h> includes <sys/types.h>, but on some
44  * older systems <sys/time.h> does not include
45  * <sys/types.h>, so we include it explicitly.
46  */
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #if defined(AIX)
50 #include <sys/select.h>
51 #endif
52 
53 #define HAVE_NETINET_TCP_H
54 
55 #define _PR_HAVE_O_APPEND
56 
57 #define PR_DIRECTORY_SEPARATOR      '/'
58 #define PR_DIRECTORY_SEPARATOR_STR  "/"
59 #define PR_PATH_SEPARATOR       ':'
60 #define PR_PATH_SEPARATOR_STR       ":"
61 typedef int (*FARPROC)();
62 
63 /*
64  * intervals at which GLOBAL threads wakeup to check for pending interrupt
65  */
66 #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
67 extern PRIntervalTime intr_timeout_ticks;
68 
69 /*
70  * The bit flags for the in_flags and out_flags fields
71  * of _PR_UnixPollDesc
72  */
73 #ifdef _PR_USE_POLL
74 #define _PR_UNIX_POLL_READ    POLLIN
75 #define _PR_UNIX_POLL_WRITE   POLLOUT
76 #define _PR_UNIX_POLL_EXCEPT  POLLPRI
77 #define _PR_UNIX_POLL_ERR     POLLERR
78 #define _PR_UNIX_POLL_NVAL    POLLNVAL
79 #define _PR_UNIX_POLL_HUP     POLLHUP
80 #else /* _PR_USE_POLL */
81 #define _PR_UNIX_POLL_READ    0x1
82 #define _PR_UNIX_POLL_WRITE   0x2
83 #define _PR_UNIX_POLL_EXCEPT  0x4
84 #define _PR_UNIX_POLL_ERR     0x8
85 #define _PR_UNIX_POLL_NVAL    0x10
86 #define _PR_UNIX_POLL_HUP     0x20
87 #endif /* _PR_USE_POLL */
88 
89 typedef struct _PRUnixPollDesc {
90     PRInt32 osfd;
91     PRInt16 in_flags;
92     PRInt16 out_flags;
93 } _PRUnixPollDesc;
94 
95 typedef struct PRPollQueue {
96     PRCList links;        /* for linking PRPollQueue's together */
97     _PRUnixPollDesc *pds;        /* array of poll descriptors */
98     PRUintn npds;            /* length of the array */
99     PRPackedBool on_ioq;    /* is this on the async i/o work q? */
100     PRIntervalTime timeout;        /* timeout, in ticks */
101     struct PRThread *thr;
102 } PRPollQueue;
103 
104 #define _PR_POLLQUEUE_PTR(_qp) \
105     ((PRPollQueue*) ((char*) (_qp) - offsetof(PRPollQueue,links)))
106 
107 
108 extern PRInt32 _PR_WaitForMultipleFDs(
109     _PRUnixPollDesc *unixpds,
110     PRInt32 pdcnt,
111     PRIntervalTime timeout);
112 extern void _PR_Unblock_IO_Wait(struct PRThread *thr);
113 
114 #if defined(_PR_LOCAL_THREADS_ONLY) || defined(_PR_GLOBAL_THREADS_ONLY)
115 #define _MD_CHECK_FOR_EXIT()
116 #endif
117 
118 extern fd_set _pr_md_read_set, _pr_md_write_set, _pr_md_exception_set;
119 extern PRInt16 _pr_md_read_cnt[], _pr_md_write_cnt[], _pr_md_exception_cnt[];
120 extern PRInt32 _pr_md_ioq_max_osfd;
121 extern PRUint32 _pr_md_ioq_timeout;
122 
123 struct _MDFileDesc {
124     int osfd;
125 #if defined(LINUX) && defined(_PR_PTHREADS)
126     int tcp_nodelay;  /* used by pt_LinuxSendFile */
127 #endif
128 };
129 
130 struct _MDDir {
131     DIR *d;
132 };
133 
134 struct _PRCPU;
135 extern void _MD_unix_init_running_cpu(struct _PRCPU *cpu);
136 
137 /*
138 ** Make a redzone at both ends of the stack segment. Disallow access
139 ** to those pages of memory. It's ok if the mprotect call's don't
140 ** work - it just means that we don't really have a functional
141 ** redzone.
142 */
143 #include <sys/mman.h>
144 #ifndef PROT_NONE
145 #define PROT_NONE 0x0
146 #endif
147 
148 #if defined(DEBUG) && !defined(DARWIN)
149 #if !defined(SOLARIS)
150 #include <string.h>  /* for memset() */
151 #define _MD_INIT_STACK(ts,REDZONE)                  \
152     PR_BEGIN_MACRO                                  \
153     (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_NONE); \
154     (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\
155             REDZONE, PROT_NONE);                \
156     /*                                  \
157     ** Fill stack memory with something that turns into an illegal  \
158     ** pointer value. This will sometimes find runtime references to    \
159     ** uninitialized pointers. We don't do this for solaris because we  \
160     ** can use purify instead.                      \
161     */                                  \
162     if (_pr_debugStacks) {                      \
163     memset(ts->allocBase + REDZONE, 0xf7, ts->stackSize);       \
164     }                                   \
165     PR_END_MACRO
166 #else   /* !SOLARIS */
167 #define _MD_INIT_STACK(ts,REDZONE)                  \
168     PR_BEGIN_MACRO                                  \
169     (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_NONE); \
170     (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\
171             REDZONE, PROT_NONE);                \
172     PR_END_MACRO
173 #endif  /* !SOLARIS */
174 
175 /*
176  * _MD_CLEAR_STACK
177  *  Allow access to the redzone pages; the access was turned off in
178  *  _MD_INIT_STACK.
179  */
180 #define _MD_CLEAR_STACK(ts)                     \
181     PR_BEGIN_MACRO                                  \
182     (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_READ|PROT_WRITE);\
183     (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\
184             REDZONE, PROT_READ|PROT_WRITE);         \
185     PR_END_MACRO
186 
187 #else   /* DEBUG */
188 
189 #define _MD_INIT_STACK(ts,REDZONE)
190 #define _MD_CLEAR_STACK(ts)
191 
192 #endif  /* DEBUG */
193 
194 #if !defined(SOLARIS)
195 
196 #define PR_SET_INTSOFF(newval)
197 
198 #endif
199 
200 /************************************************************************/
201 
202 extern void _PR_UnixInit(void);
203 
204 extern void _PR_UnixCleanup(void);
205 #define _MD_EARLY_CLEANUP _PR_UnixCleanup
206 
207 /************************************************************************/
208 
209 struct _MDProcess {
210     pid_t pid;
211 };
212 
213 struct PRProcess;
214 struct PRProcessAttr;
215 
216 /* Create a new process (fork() + exec()) */
217 #define _MD_CREATE_PROCESS _MD_CreateUnixProcess
218 extern struct PRProcess * _MD_CreateUnixProcess(
219     const char *path,
220     char *const *argv,
221     char *const *envp,
222     const struct PRProcessAttr *attr
223 );
224 
225 #define _MD_DETACH_PROCESS _MD_DetachUnixProcess
226 extern PRStatus _MD_DetachUnixProcess(struct PRProcess *process);
227 
228 /* Wait for a child process to terminate */
229 #define _MD_WAIT_PROCESS _MD_WaitUnixProcess
230 extern PRStatus _MD_WaitUnixProcess(struct PRProcess *process,
231                                     PRInt32 *exitCode);
232 
233 #define _MD_KILL_PROCESS _MD_KillUnixProcess
234 extern PRStatus _MD_KillUnixProcess(struct PRProcess *process);
235 
236 /************************************************************************/
237 
238 extern void _MD_EnableClockInterrupts(void);
239 extern void _MD_DisableClockInterrupts(void);
240 
241 #define _MD_START_INTERRUPTS            _MD_StartInterrupts
242 #define _MD_STOP_INTERRUPTS             _MD_StopInterrupts
243 #define _MD_DISABLE_CLOCK_INTERRUPTS    _MD_DisableClockInterrupts
244 #define _MD_ENABLE_CLOCK_INTERRUPTS     _MD_EnableClockInterrupts
245 #define _MD_BLOCK_CLOCK_INTERRUPTS      _MD_BlockClockInterrupts
246 #define _MD_UNBLOCK_CLOCK_INTERRUPTS    _MD_UnblockClockInterrupts
247 
248 /************************************************************************/
249 
250 extern void     _MD_InitCPUS(void);
251 #define _MD_INIT_CPUS           _MD_InitCPUS
252 
253 extern void     _MD_Wakeup_CPUs(void);
254 #define _MD_WAKEUP_CPUS _MD_Wakeup_CPUs
255 
256 #define _MD_PAUSE_CPU           _MD_PauseCPU
257 
258 #if defined(_PR_LOCAL_THREADS_ONLY) || defined(_PR_GLOBAL_THREADS_ONLY)
259 #define _MD_CLEANUP_BEFORE_EXIT()
260 #endif
261 
262 #define _MD_EXIT(status)        _exit(status)
263 
264 /************************************************************************/
265 
266 #define _MD_GET_ENV             getenv
267 #define _MD_PUT_ENV             putenv
268 
269 /************************************************************************/
270 
271 #define _MD_INIT_FILEDESC(fd)
272 
273 extern void     _MD_MakeNonblock(PRFileDesc *fd);
274 #define _MD_MAKE_NONBLOCK           _MD_MakeNonblock
275 
276 /************************************************************************/
277 
278 #if !defined(_PR_PTHREADS)
279 
280 extern void     _MD_InitSegs(void);
281 extern PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size,
282                                  void *vaddr);
283 extern void     _MD_FreeSegment(PRSegment *seg);
284 
285 #define _MD_INIT_SEGS           _MD_InitSegs
286 #define _MD_ALLOC_SEGMENT       _MD_AllocSegment
287 #define _MD_FREE_SEGMENT        _MD_FreeSegment
288 
289 #endif /* !defined(_PR_PTHREADS) */
290 
291 /************************************************************************/
292 
293 #ifdef _MD_INTERVAL_USE_GTOD
294 extern PRIntervalTime   _PR_UNIX_GetInterval(void);
295 extern PRIntervalTime   _PR_UNIX_TicksPerSecond(void);
296 #define _MD_INTERVAL_INIT()
297 #define _MD_GET_INTERVAL        _PR_UNIX_GetInterval
298 #define _MD_INTERVAL_PER_SEC        _PR_UNIX_TicksPerSecond
299 #endif
300 
301 #ifdef _PR_HAVE_CLOCK_MONOTONIC
302 extern PRIntervalTime   _PR_UNIX_GetInterval2(void);
303 extern PRIntervalTime   _PR_UNIX_TicksPerSecond2(void);
304 #define _MD_INTERVAL_INIT()
305 #define _MD_GET_INTERVAL        _PR_UNIX_GetInterval2
306 #define _MD_INTERVAL_PER_SEC        _PR_UNIX_TicksPerSecond2
307 #endif
308 
309 #define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000)
310 #define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000)
311 
312 /************************************************************************/
313 
314 #define _MD_ERRNO()                 (errno)
315 #define _MD_GET_SOCKET_ERROR()      (errno)
316 
317 /************************************************************************/
318 
319 extern PRInt32 _MD_AvailableSocket(PRInt32 osfd);
320 
321 extern void _MD_StartInterrupts(void);
322 extern void _MD_StopInterrupts(void);
323 extern void _MD_DisableClockInterrupts(void);
324 extern void _MD_BlockClockInterrupts(void);
325 extern void _MD_UnblockClockInterrupts(void);
326 extern void _MD_PauseCPU(PRIntervalTime timeout);
327 
328 extern PRStatus _MD_open_dir(struct _MDDir *, const char *);
329 extern PRInt32  _MD_close_dir(struct _MDDir *);
330 extern char *   _MD_read_dir(struct _MDDir *, PRIntn);
331 extern PRInt32  _MD_open(const char *name, PRIntn osflags, PRIntn mode);
332 extern PRInt32  _MD_delete(const char *name);
333 extern PRInt32  _MD_getfileinfo(const char *fn, PRFileInfo *info);
334 extern PRInt32  _MD_getfileinfo64(const char *fn, PRFileInfo64 *info);
335 extern PRInt32  _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info);
336 extern PRInt32  _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info);
337 extern PRInt32  _MD_rename(const char *from, const char *to);
338 extern PRInt32  _MD_access(const char *name, PRAccessHow how);
339 extern PRInt32  _MD_mkdir(const char *name, PRIntn mode);
340 extern PRInt32  _MD_rmdir(const char *name);
341 extern PRInt32  _MD_accept_read(PRInt32 sock, PRInt32 *newSock,
342                                 PRNetAddr **raddr, void *buf, PRInt32 amount);
343 extern PRInt32  _PR_UnixSendFile(PRFileDesc *sd, PRSendFileData *sfd,
344                                  PRTransmitFileFlags flags, PRIntervalTime timeout);
345 
346 extern PRStatus _MD_LockFile(PRInt32 osfd);
347 extern PRStatus _MD_TLockFile(PRInt32 osfd);
348 extern PRStatus _MD_UnlockFile(PRInt32 osfd);
349 
350 #define _MD_OPEN_DIR(dir, name)         _MD_open_dir(dir, name)
351 #define _MD_CLOSE_DIR(dir)              _MD_close_dir(dir)
352 #define _MD_READ_DIR(dir, flags)        _MD_read_dir(dir, flags)
353 #define _MD_OPEN(name, osflags, mode)   _MD_open(name, osflags, mode)
354 #define _MD_OPEN_FILE(name, osflags, mode)  _MD_open(name, osflags, mode)
355 extern PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount);
356 #define _MD_READ(fd,buf,amount)         _MD_read(fd,buf,amount)
357 extern PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount);
358 #define _MD_WRITE(fd,buf,amount)        _MD_write(fd,buf,amount)
359 #define _MD_DELETE(name)                _MD_delete(name)
360 #define _MD_GETFILEINFO(fn, info)       _MD_getfileinfo(fn, info)
361 #define _MD_GETFILEINFO64(fn, info)     _MD_getfileinfo64(fn, info)
362 #define _MD_GETOPENFILEINFO(fd, info)   _MD_getopenfileinfo(fd, info)
363 #define _MD_GETOPENFILEINFO64(fd, info) _MD_getopenfileinfo64(fd, info)
364 #define _MD_RENAME(from, to)            _MD_rename(from, to)
365 #define _MD_ACCESS(name, how)           _MD_access(name, how)
366 #define _MD_MKDIR(name, mode)           _MD_mkdir(name, mode)
367 #define _MD_MAKE_DIR(name, mode)        _MD_mkdir(name, mode)
368 #define _MD_RMDIR(name)                 _MD_rmdir(name)
369 #define _MD_ACCEPT_READ(sock, newSock, raddr, buf, amount)  _MD_accept_read(sock, newSock, raddr, buf, amount)
370 
371 #define _MD_LOCKFILE _MD_LockFile
372 #define _MD_TLOCKFILE _MD_TLockFile
373 #define _MD_UNLOCKFILE _MD_UnlockFile
374 
375 
376 extern PRInt32      _MD_socket(int af, int type, int flags);
377 #define _MD_SOCKET  _MD_socket
378 extern PRInt32      _MD_connect(PRFileDesc *fd, const PRNetAddr *addr,
379                                 PRUint32 addrlen, PRIntervalTime timeout);
380 #define _MD_CONNECT _MD_connect
381 extern PRInt32      _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
382                                PRIntervalTime timeout);
383 #define _MD_ACCEPT  _MD_accept
384 extern PRInt32      _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen);
385 #define _MD_BIND    _MD_bind
386 extern PRInt32      _MD_listen(PRFileDesc *fd, PRIntn backlog);
387 #define _MD_LISTEN  _MD_listen
388 extern PRInt32      _MD_shutdown(PRFileDesc *fd, PRIntn how);
389 #define _MD_SHUTDOWN    _MD_shutdown
390 
391 extern PRInt32      _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
392                              PRIntn flags, PRIntervalTime timeout);
393 #define _MD_RECV    _MD_recv
394 extern PRInt32      _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
395                              PRIntn flags, PRIntervalTime timeout);
396 #define _MD_SEND    _MD_send
397 extern PRInt32      _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
398                                  PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
399                                  PRIntervalTime timeout);
400 #define _MD_RECVFROM    _MD_recvfrom
401 extern PRInt32 _MD_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount,
402                           PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen,
403                           PRIntervalTime timeout);
404 #define _MD_SENDTO  _MD_sendto
405 extern PRInt32      _MD_writev(PRFileDesc *fd, const struct PRIOVec *iov,
406                                PRInt32 iov_size, PRIntervalTime timeout);
407 #define _MD_WRITEV  _MD_writev
408 
409 extern PRInt32      _MD_socketavailable(PRFileDesc *fd);
410 #define _MD_SOCKETAVAILABLE     _MD_socketavailable
411 extern PRInt64      _MD_socketavailable64(PRFileDesc *fd);
412 #define _MD_SOCKETAVAILABLE64       _MD_socketavailable64
413 
414 #define _MD_PIPEAVAILABLE       _MD_socketavailable
415 
416 extern PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds,
417                            PRIntervalTime timeout);
418 #define _MD_PR_POLL     _MD_pr_poll
419 
420 extern PRInt32      _MD_close(PRInt32 osfd);
421 #define _MD_CLOSE_FILE  _MD_close
422 extern PRInt32      _MD_lseek(PRFileDesc*, PRInt32, PRSeekWhence);
423 #define _MD_LSEEK   _MD_lseek
424 extern PRInt64      _MD_lseek64(PRFileDesc*, PRInt64, PRSeekWhence);
425 #define _MD_LSEEK64 _MD_lseek64
426 extern PRInt32      _MD_fsync(PRFileDesc *fd);
427 #define _MD_FSYNC   _MD_fsync
428 
429 extern PRInt32 _MD_socketpair(int af, int type, int flags, PRInt32 *osfd);
430 #define _MD_SOCKETPAIR      _MD_socketpair
431 
432 #define _MD_CLOSE_SOCKET    _MD_close
433 
434 #ifndef NO_NSPR_10_SUPPORT
435 #define _MD_STAT    stat
436 #endif
437 
438 extern PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
439                                 PRUint32 *addrlen);
440 #define _MD_GETPEERNAME _MD_getpeername
441 extern PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
442                                 PRUint32 *addrlen);
443 #define _MD_GETSOCKNAME _MD_getsockname
444 
445 extern PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,
446                                PRInt32 optname, char* optval, PRInt32* optlen);
447 #define _MD_GETSOCKOPT      _MD_getsockopt
448 extern PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level,
449                                PRInt32 optname, const char* optval, PRInt32 optlen);
450 #define _MD_SETSOCKOPT      _MD_setsockopt
451 
452 extern PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable);
453 #define _MD_SET_FD_INHERITABLE _MD_set_fd_inheritable
454 
455 extern void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported);
456 #define _MD_INIT_FD_INHERITABLE _MD_init_fd_inheritable
457 
458 extern void _MD_query_fd_inheritable(PRFileDesc *fd);
459 #define _MD_QUERY_FD_INHERITABLE _MD_query_fd_inheritable
460 
461 extern PRStatus _MD_gethostname(char *name, PRUint32 namelen);
462 #define _MD_GETHOSTNAME     _MD_gethostname
463 
464 extern PRStatus _MD_getsysinfo(PRSysInfo cmd, char *name, PRUint32 namelen);
465 #define _MD_GETSYSINFO      _MD_getsysinfo
466 
467 extern int _MD_unix_get_nonblocking_connect_error(int osfd);
468 
469 /* Memory-mapped files */
470 
471 struct _MDFileMap {
472     PRIntn prot;
473     PRIntn flags;
474     PRBool isAnonFM; /* when true, PR_CloseFileMap() must close the related fd */
475 };
476 
477 extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size);
478 #define _MD_CREATE_FILE_MAP _MD_CreateFileMap
479 
480 #define _MD_GET_MEM_MAP_ALIGNMENT() PR_GetPageSize()
481 
482 extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset,
483                          PRUint32 len);
484 #define _MD_MEM_MAP _MD_MemMap
485 
486 extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
487 #define _MD_MEM_UNMAP _MD_MemUnmap
488 
489 extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
490 #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
491 
492 extern PRStatus _MD_SyncMemMap(
493     PRFileDesc *fd,
494     void *addr,
495     PRUint32 len);
496 #define _MD_SYNC_MEM_MAP _MD_SyncMemMap
497 
498 /*
499  * The standard (XPG4) gettimeofday() (from BSD) takes two arguments.
500  * On some SVR4 derivatives, gettimeofday() takes only one argument.
501  * The GETTIMEOFDAY macro is intended to hide this difference.
502  */
503 #ifdef HAVE_SVID_GETTOD
504 #define GETTIMEOFDAY(tp) gettimeofday(tp)
505 #else
506 #define GETTIMEOFDAY(tp) gettimeofday((tp), NULL)
507 #endif
508 
509 #if defined(_PR_PTHREADS) && !defined(_PR_POLL_AVAILABLE)
510 #define _PR_NEED_FAKE_POLL
511 #endif
512 
513 #if defined(_PR_NEED_FAKE_POLL)
514 
515 /*
516  * Some platforms don't have poll(), but our pthreads code calls poll().
517  * As a temporary measure, I implemented a fake poll() using select().
518  * Here are the struct and macro definitions copied from sys/poll.h
519  * on Solaris 2.5.
520  */
521 
522 struct pollfd {
523     int fd;
524     short events;
525     short revents;
526 };
527 
528 /* poll events */
529 
530 #define POLLIN      0x0001      /* fd is readable */
531 #define POLLPRI     0x0002      /* high priority info at fd */
532 #define POLLOUT     0x0004      /* fd is writeable (won't block) */
533 #define POLLRDNORM  0x0040      /* normal data is readable */
534 #define POLLWRNORM  POLLOUT
535 #define POLLRDBAND  0x0080      /* out-of-band data is readable */
536 #define POLLWRBAND  0x0100      /* out-of-band data is writeable */
537 
538 #define POLLNORM    POLLRDNORM
539 
540 #define POLLERR     0x0008      /* fd has error condition */
541 #define POLLHUP     0x0010      /* fd has been hung up on */
542 #define POLLNVAL    0x0020      /* invalid pollfd entry */
543 
544 extern int poll(struct pollfd *, unsigned long, int);
545 
546 #endif /* _PR_NEED_FAKE_POLL */
547 
548 /*
549 ** A vector of the UNIX I/O calls we use. These are here to smooth over
550 ** the rough edges needed for large files. All of NSPR's implmentaions
551 ** go through this vector using syntax of the form
552 **      result = _md_iovector.xxx64(args);
553 */
554 
555 #if defined(SOLARIS2_5)
556 /*
557 ** Special case: Solaris 2.5.1
558 ** Solaris starts to have 64-bit file I/O in 2.6.  We build on Solaris
559 ** 2.5.1 so that we can use the same binaries on both Solaris 2.5.1 and
560 ** 2.6.  At run time, we detect whether 64-bit file I/O is available by
561 ** looking up the 64-bit file function symbols in libc.  At build time,
562 ** we need to define the 64-bit file I/O datatypes that are compatible
563 ** with their definitions on Solaris 2.6.
564 */
565 typedef PRInt64 off64_t;
566 typedef PRUint64 ino64_t;
567 typedef PRInt64 blkcnt64_t;
568 struct stat64 {
569     dev_t st_dev;
570     long st_pad1[3];
571     ino64_t st_ino;
572     mode_t st_mode;
573     nlink_t st_nlink;
574     uid_t st_uid;
575     gid_t st_gid;
576     dev_t st_rdev;
577     long t_pad2[2];
578     off64_t st_size;
579     timestruc_t st_atim;
580     timestruc_t st_mtim;
581     timestruc_t st_ctim;
582     long st_blksize;
583     blkcnt64_t st_blocks;
584     char st_fstype[_ST_FSTYPSZ];
585     long st_pad4[8];
586 };
587 typedef struct stat64 _MDStat64;
588 typedef off64_t _MDOff64_t;
589 
590 #elif defined(_PR_HAVE_OFF64_T)
591 typedef struct stat64 _MDStat64;
592 typedef off64_t _MDOff64_t;
593 #elif defined(_PR_HAVE_LARGE_OFF_T)
594 typedef struct stat _MDStat64;
595 typedef off_t _MDOff64_t;
596 #elif defined(_PR_NO_LARGE_FILES)
597 typedef struct stat _MDStat64;
598 typedef PRInt64 _MDOff64_t;
599 #else
600 #error "I don't know yet"
601 #endif
602 
603 typedef PRIntn (*_MD_Fstat64)(PRIntn osfd, _MDStat64 *buf);
604 typedef PRIntn (*_MD_Open64)(const char *path, int oflag, ...);
605 typedef PRIntn (*_MD_Stat64)(const char *path, _MDStat64 *buf);
606 typedef _MDOff64_t (*_MD_Lseek64)(PRIntn osfd, _MDOff64_t, PRIntn whence);
607 typedef void* (*_MD_Mmap64)(
608     void *addr, PRSize len, PRIntn prot, PRIntn flags,
609     PRIntn fildes, _MDOff64_t offset);
610 struct _MD_IOVector
611 {
612     _MD_Open64 _open64;
613     _MD_Mmap64 _mmap64;
614     _MD_Stat64 _stat64;
615     _MD_Fstat64 _fstat64;
616     _MD_Lseek64 _lseek64;
617 };
618 extern struct _MD_IOVector _md_iovector;
619 
620 #endif /* prunixos_h___ */
621