Home | History | Annotate | Download | only in sys
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the License).
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/CDDL.txt
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/CDDL.txt.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets [] replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
     28 /*	  All Rights Reserved   */
     29 
     30 /*
     31  * The following notices accompanied the original version of this file:
     32  *
     33  * Copyright (c) 1982, 1986 Regents of the University of California.
     34  * All rights reserved.  The Berkeley software License Agreement
     35  * specifies the terms and conditions for redistribution.
     36  */
     37 
     38 #ifndef _OS_H
     39 #define	_OS_H
     40 
     41 #pragma ident	"@(#)os.h	1.125	08/07/17 SMI"
     42 
     43 #ifdef __cplusplus
     44 extern "C" {
     45 #endif
     46 
     47 #ifdef __cplusplus
     48 }
     49 #endif
     50 
     51 #include <sys/os_compat.h>
     52 
     53 #if defined(__cplusplus)
     54 
     55 /*
     56  * os.h - specification of the OS services that Solaris MC components
     57  *	  can call from C++ in a portable way both in userland and in
     58  *	  the kernel.
     59  */
     60 
     61 #include <sys/types.h>
     62 #if __cplusplus < 199711
     63 /* For emulation "bool" type till compiler supports built-in bool type */
     64 #include <sys/boolean.h>
     65 #endif
     66 
     67 #ifndef linux
     68 #define	BUG_4630016
     69 #endif
     70 
     71 #ifdef BUG_4630016
     72 #ifndef _KERNEL
     73 #define	_KERNEL
     74 #include <sys/atomic.h>
     75 #undef _KERNEL
     76 #else // _KERNEL
     77 #include <sys/atomic.h>
     78 #endif // _KERNEL
     79 #endif
     80 
     81 #ifndef linux
     82 #include <sys/systm.h>
     83 #endif
     84 #include <sys/time.h>
     85 #include <orb/infrastructure/fork.h>
     86 
     87 #if defined(DEBUG)
     88 #define	INTR_DEBUG
     89 #endif
     90 
     91 extern "C" {
     92 	void symtracedump(void);
     93 }
     94 
     95 #include <netdb.h>
     96 #include <netinet/in.h>
     97 #include <sys/cl_assert.h>
     98 
     99 #ifdef linux
    100 #include <pthread.h>
    101 #include <semaphore.h>
    102 #endif
    103 
    104 #ifdef	_KERNEL
    105 #ifndef	linux
    106 #include <sys/thread.h>
    107 #include <sys/mutex.h>
    108 #include <sys/rwlock.h>
    109 #include <sys/ksynch.h>
    110 #include <sys/proc.h>
    111 #include <sys/stack.h>
    112 #include <sys/strsubr.h>
    113 #include <sys/kmem.h>
    114 #include <sys/debug.h>
    115 #include <sys/bitmap.h>
    116 #include <sys/kobj.h>
    117 #include <sys/dirent.h>
    118 #endif	/* linux */
    119 
    120 #else	// _KERNEL
    121 
    122 #include <stdio.h>	// for BUFSIZ
    123 #include <stdlib.h>	// for atoi
    124 #ifdef linux
    125 #include <pthread.h>
    126 #include <semaphore.h>
    127 #else
    128 #include <thread.h>
    129 #include <synch.h>
    130 #endif
    131 #include <string.h>
    132 #include <errno.h>
    133 #include <strings.h>
    134 #include <ctype.h>
    135 #include <unistd.h>
    136 #include <dirent.h>
    137 #include <pwd.h>
    138 
    139 #define	ATOMIC_HASH_SIZE	256
    140 #define	ATOMIC_HASH_SHIFT	6
    141 #define	ATOMIC_HASH(addr)	\
    142 	(((uintptr_t)(addr)	>> ATOMIC_HASH_SHIFT) & ATOMIC_HASH_MASK)
    143 #define	ATOMIC_HASH_MASK		(ATOMIC_HASH_SIZE - 1)
    144 
    145 #define	ATOMIC_LOCK(addr)		&atomic_lock[ATOMIC_HASH(addr)]
    146 
    147 #endif	// _KERNEL
    148 
    149 #include <sys/sc_syslog_msg.h> // for sc_syslog_msg class
    150 
    151 #ifdef u
    152 #undef u
    153 #endif
    154 
    155 #ifdef paddr
    156 #undef paddr
    157 #endif
    158 
    159 #ifndef	NULL
    160 #define	NULL 0
    161 #endif
    162 
    163 //
    164 // OS dependent functions needed for C/C++ programs
    165 //
    166 extern "C" int mkdirp(const char *path, mode_t mode);
    167 extern "C" hrtime_t gethrtime();
    168 #ifdef linux
    169 extern "C" int getnetbyname_r(const char*, struct netent*, char*, size_t,
    170     struct netent**, int*);
    171 extern "C" int getrpcbyname_r(const char*, struct rpcent*, char*, size_t,
    172 	struct rpcent**) throw();
    173 #else
    174 extern "C" struct netent *getnetbyname_r(const char *, struct netent*,
    175 	char*, int);
    176 extern "C" struct rpcent *getrpcbyname_r(const char *, struct rpcent*,
    177 	char*, int);
    178 #endif
    179 extern "C" struct hostent *getipnodebyname(const char *name, int af,
    180 	int flags, int *error_num);
    181 extern "C" void freehostent(struct hostent *hp);
    182 
    183 
    184 //
    185 // maxusers - unode version defines the maximum number of users
    186 // a unode system supports. This really is used for system
    187 // configuration.
    188 //
    189 extern int maxusers;
    190 #ifndef linux
    191 #include <sys/clconf.h>
    192 #ifndef _KERNEL
    193 extern void	clconf_init(void);
    194 extern nodeid_t	clconf_get_nodeid(void);
    195 #endif
    196 #else
    197 extern void clconf_init();
    198 #endif
    199 
    200 //
    201 // The namespace os:: includes those OS services that Solaris MC components
    202 // can call from C++ in a portable way. Both userland and kernel level
    203 // implementations of this API are provided.
    204 //
    205 // The C equivalent of this API is defined in <os_c.h>
    206 //
    207 
    208 class os {
    209 public:
    210 #ifdef _KERNEL
    211 	enum mem_alloc_type { SLEEP = KM_SLEEP, NO_SLEEP = KM_NOSLEEP };
    212 #else
    213 	enum mem_alloc_type { SLEEP, NO_SLEEP };
    214 #endif
    215 	enum mem_zero_type { DONTZERO, ZERO };
    216 
    217 #ifdef _KERNEL
    218 	typedef kthread_t *threadid_t;
    219 #else
    220 	typedef thread_t threadid_t;
    221 #endif
    222 	static os::threadid_t threadid();
    223 
    224 	class condvar_t;	// forward declaration
    225 
    226 	//
    227 	// class mutex - synchronization mutex
    228 	//
    229 	class mutex_t {
    230 		friend class condvar_t;
    231 #ifndef	_KERNEL
    232 		//
    233 		// following friend class defines pthread_atfork handler
    234 		// functions. This is defined friend of mutex class so that
    235 		// the owner of the lock can be updated to new threadid
    236 		// in the child process.
    237 		//
    238 		friend class pthread_atfork_handler;
    239 #endif	// _KERNEL
    240 	public:
    241 		mutex_t();
    242 		~mutex_t();
    243 		void lock();
    244 		int try_lock();
    245 		void unlock();
    246 		int lock_held();
    247 		int lock_not_held();
    248 		uint64_t owner();
    249 
    250 	private:
    251 		//
    252 		// when a process fork's a child, it may inherit a lock
    253 		// in a locked state, and the owner of the lock is set to
    254 		// threadid of the locking  thread of the parent.
    255 		// The owner of lock should be set to threadid of the locking
    256 		// thread in the child process. This interface is called by
    257 		// the child handler defined in fork.cc  so as to set the
    258 		// owner of the lock to threadid in the child process.
    259 		//
    260 		// Note: this interface should be called only by
    261 		// pthread_handler's defined in fork.cc.
    262 		//
    263 		void set_owner();
    264 #ifdef	_KERNEL
    265 		::kmutex_t _mutex;
    266 #else	// _KERNEL
    267 #ifdef linux
    268 		::pthread_mutex_t _mutex;
    269 #else
    270 		::mutex_t _mutex;
    271 #endif
    272 		os::threadid_t _owner;	// For lock held and assertions
    273 #endif	// _KERNEL
    274 
    275 		// Disallow assignments and pass by value
    276 		mutex_t(const mutex_t &);
    277 		mutex_t &operator = (mutex_t &);
    278 	};
    279 
    280 	//
    281 	// class rwlock_t - reader/writer lock
    282 	//
    283 	class rwlock_t {
    284 	public:
    285 		rwlock_t();
    286 		~rwlock_t();
    287 		void rdlock();
    288 		void wrlock();
    289 		int try_rdlock();
    290 		int try_wrlock();
    291 		void unlock();
    292 		int lock_held();
    293 		int read_held();
    294 		int write_held();
    295 #ifdef	_KERNEL
    296 		//
    297 		// The methods try_upgrade(), downgrade(), and rw_owner()
    298 		// are not supported in userland.  There is no
    299 		// corresponding Solaris system call to wrap around.
    300 		//
    301 
    302 		int try_upgrade();
    303 		void downgrade();
    304 		threadid_t rw_owner();
    305 #endif
    306 	private:
    307 #ifdef	_KERNEL
    308 		::krwlock_t _rwlock;
    309 #else	// _KERNEL
    310 #ifdef linux
    311 		::pthread_rwlock_t _rwlock;
    312 #else
    313 		::rwlock_t _rwlock;
    314 #endif
    315 #endif	// _KERNEL
    316 
    317 		// Disallow assignments and pass by value
    318 		rwlock_t(const rwlock_t &);
    319 		rwlock_t &operator = (rwlock_t &);
    320 	};
    321 
    322 	class systime;
    323 
    324 	//
    325 	// functions for atomic operations { see <sys/atomic.h> }
    326 	// add delta atomically to tgt
    327 	//
    328 	static void atomic_add_16(uint16_t *tgt, int16_t delta);
    329 	static void atomic_add_32(uint32_t *tgt, int32_t delta);
    330 	static void atomic_add_64(uint64_t *tgt, int64_t delta);
    331 	//
    332 	// as above, but also return final value of target
    333 	//
    334 	static uint16_t atomic_add_16_nv(uint16_t *tgt, int16_t delta);
    335 	static uint32_t atomic_add_32_nv(uint32_t *tgt, int32_t delta);
    336 	static uint64_t atomic_add_64_nv(uint64_t *tgt, int64_t delta);
    337 
    338 #ifdef _KERNEL
    339 	//
    340 	// compare and swap if tgt == cmp then set tgt to nv
    341 	// and return old value of tgt
    342 	//
    343 	// If there are requirements for user-land versions of the
    344 	// cas* functions, atomic_cas_32(3C), atomic_cas_64(3C) and
    345 	// atomic_cas_ptr(3C) can be used.
    346 	//
    347 	static uint32_t cas32(uint32_t *tgt, uint32_t cmp, uint32_t nv);
    348 	static uint64_t cas64(uint64_t *tgt, uint64_t cmp, uint64_t nv);
    349 	//
    350 	// as above, but with pointers
    351 	//
    352 	static void    *casptr(void **tgt, void *cmp, void *nval);
    353 	//
    354 	// end of atomic operations from <sys/atomic.h>
    355 	//
    356 #endif 	// _KERNEL
    357 
    358 	//
    359 	// Atomic copies (for guaranteed atomic copies across architectures)
    360 	// This function makes no guarantees as to atomic reads.  If you want
    361 	// to read atomically, use this function to make a local copy and read
    362 	// that.  Both arguments must point to addresses that are 8 byte
    363 	// aligned.
    364 	//
    365 	static void atomic_copy_64(uint64_t *tgt, uint64_t *src);
    366 
    367 	//
    368 	// variations of allocb/dupb that support os::SLEEP allocations
    369 	// XX Currently implemented in _KERNEL only,
    370 	// would be nice to have user land emulation too
    371 	//
    372 	static mblk_t *allocb(uint_t size, uint_t pri, os::mem_alloc_type flag);
    373 	static mblk_t *dupb(mblk_t *mp, uint_t pri, os::mem_alloc_type flag);
    374 
    375 	//
    376 	// class condvar - condition variable
    377 	//
    378 	// The condvar can only be used with one lock.
    379 	// The first lock used with the condvar becomes the only lock
    380 	// which the condvar will accept subsequently.
    381 	//
    382 	class condvar_t {
    383 	public:
    384 		condvar_t();
    385 		~condvar_t();
    386 
    387 		//
    388 		// These result values correspond to those returned by the
    389 		// kernel so that kernel developers may use the actual values
    390 		// if they prefer.
    391 		//
    392 		enum wait_result { SIGNALED = 0, TIMEDOUT = -1, NORMAL = 1 };
    393 
    394 		// There are 4 variants on wait. The userland version of the
    395 		// wait() and timedwait() can be woken by signals or fork. If
    396 		// they are NORMAL is returned.
    397 		//
    398 		// For user, if there is no signal handler defined for the
    399 		// signal in question, the program will segv.
    400 		void	wait(mutex_t *lockp);
    401 		// returns NORMAL or SIGNALED.
    402 		wait_result wait_sig(mutex_t *lockp);
    403 		// returns NORMAL or TIMEDOUT
    404 		wait_result timedwait(mutex_t *lockp, systime *timeout);
    405 		// returns NORMAL or SIGNALED or TIMEDOUT
    406 		wait_result timedwait_sig(mutex_t *lockp, systime *timeout);
    407 
    408 		void	signal();
    409 		void	broadcast();
    410 
    411 #ifdef DEBUG
    412 		//
    413 		// The condvar_t will no longer use the lock currently
    414 		// associated with it and the condvar_t is idle.
    415 		// Reset the condvar_t to its initial state.
    416 		//
    417 		void	reset();
    418 #endif
    419 
    420 	private:
    421 
    422 #ifdef linux
    423 		::pthread_cond_t _cv;
    424 #else	/* linux */
    425 #ifdef	_KERNEL
    426 		::kcondvar_t _cv;
    427 #else	// _KERNEL
    428 		::cond_t _cv;
    429 #endif
    430 #endif	// _KERNEL
    431 
    432 		// Called before wait.
    433 		void debug_pre(os::mutex_t *lockp);
    434 		// Called after wait.
    435 		void debug_post();
    436 #ifdef DEBUG
    437 		int		num_waiting;
    438 		os::mutex_t	*wait_lock;	// Only this lock can be used,
    439 						// once set
    440 #endif
    441 
    442 		// Disallow assignments and pass by value
    443 		condvar_t(const condvar_t &);
    444 		condvar_t &operator = (condvar_t &);
    445 	};
    446 
    447 	// class sem_t
    448 	class sem_t {
    449 	public:
    450 		sem_t(uint_t initval);
    451 		sem_t();
    452 		~sem_t();
    453 
    454 		void	p();
    455 		int	tryp();
    456 		void	v();
    457 
    458 	private:
    459 #ifdef	_KERNEL
    460 		::ksema_t _sem;
    461 #else	// _KERNEL
    462 #ifdef linux
    463 		::sem_t _sem;
    464 #else
    465 		::sema_t _sem;
    466 #endif
    467 #endif	// _KERNEL
    468 
    469 		// Disallow assignments and pass by value
    470 		sem_t(const sem_t &);
    471 		sem_t &operator = (sem_t &);
    472 	};
    473 
    474 	//
    475 	// class notify_t
    476 	//
    477 	// Used to encapsulate a cv + flag (global mutex)
    478 	//
    479 	class notify_t {
    480 	public :
    481 		enum wait_state { WAITING, DONE };
    482 
    483 		// constructor initialized to WAITING
    484 		notify_t();
    485 
    486 		// Set flag to DONE and signal all waiters
    487 		// This does a cv.broadcast to wake up all waiters
    488 		// There is no equivalent of cv.signal as the class needs to
    489 		// be reinitialized before new waiter can wait on it.
    490 		void signal();
    491 
    492 		// Wait for flag to change state.
    493 		void wait();
    494 
    495 		// Timed Wait for flag to change state. Returns current state
    496 		wait_state timedwait(os::systime &);
    497 
    498 		// reinitialize, if old flag is WAITING, wait for old signal
    499 		// Returns 0 on failure (nonblocking only), 1 on success
    500 		int reinit(os::mem_alloc_type);
    501 
    502 		// Return current state. Mostly for debug purposes
    503 		wait_state get_state();
    504 	private	:
    505 		wait_state	flag;
    506 		os::condvar_t	cv;
    507 		static os::mutex_t notify_lock;
    508 
    509 		// Disallow assignments and pass by value
    510 		notify_t(const notify_t &);
    511 		notify_t &operator = (notify_t &);
    512 	};
    513 
    514 	//
    515 	// class thread
    516 	//
    517 
    518 	// XXX - need to declare an API to allow creation of a new thread.
    519 	class thread {
    520 	public:
    521 #ifdef _KERNEL
    522 		static os::threadid_t create(void *(*func)(void *));
    523 #else
    524 		static int create(void *, size_t, void *(*)(void *),
    525 		    void *, long, threadid_t *);
    526 #endif
    527 		static void exit(void *);
    528 		static int main(void);
    529 		static int join(threadid_t, threadid_t *departed = NULL,
    530 		    void **status = NULL);
    531 		static threadid_t self(void) { return (os::threadid()); }
    532 		static void sigsetmask(int, sigset_t *, sigset_t *);
    533 		static int getconcurrency();
    534 		static int setconcurrency(int);
    535 	};
    536 
    537 	static int drv_getparm(unsigned int, void *);
    538 	static int drv_priv(cred_t *cr);
    539 	static int sysinfo(int command, char *buf, long count);
    540 	static struct passwd *getpwnam(const char  *name,  struct  passwd
    541 	    *pwd, char *buffer, int buflen);
    542 	static struct passwd *getpwuid(uid_t  uid,  struct  passwd  *pwd,
    543 	    char *buffer, int buflen);
    544 
    545 	//
    546 	// Thread specific data
    547 	//
    548 	class tsd {
    549 	public:
    550 		typedef void (*freef_t)(void *value);
    551 		tsd(freef_t = NULL);
    552 		~tsd();
    553 		void set_tsd(uintptr_t);		// set value
    554 		uintptr_t get_tsd() const;		// get value
    555 	private:
    556 		uint_t _key;
    557 
    558 		// Disallow assignments and pass by value
    559 		tsd(const tsd &);
    560 		tsd &operator = (tsd &);
    561 	};
    562 
    563 	//
    564 	// debugging code to check for nonblocking contexts
    565 	//
    566 #ifndef linux
    567 	static
    568 #endif
    569 class envchk {
    570 	public:
    571 		//
    572 		// nbtype - defines different kinds of nonblocking context.
    573 		// The system uses these enum values to identify when
    574 		// certain operations cannot be performed.
    575 		//
    576 		enum nbtype {NB_INTR = 0x1,	// Interrupt
    577 		    NB_INVO = 0x2,		// Invocation
    578 		    NB_RECONF = 0x4};		// Node reconfiguration
    579 
    580 		static void set_nonblocking(nbtype);
    581 		static void clear_nonblocking(nbtype);
    582 		static bool is_nonblocking(int);
    583 		static void check_nonblocking(int, char *);
    584 	private:
    585 #ifdef INTR_DEBUG
    586 		static tsd env;
    587 #endif
    588 		// Disallow assignments and pass by value
    589 		envchk(const envchk &);
    590 		envchk &operator = (envchk &);
    591 	};
    592 	typedef ::hrtime_t hrtime_t;
    593 	static os::hrtime_t gethrtime();
    594 
    595 	static void tracedump();
    596 
    597 	typedef clock_t usec_t;
    598 
    599 	static void usecsleep(os::usec_t sleeptime);
    600 
    601 	//
    602 	// Methods for time of day computations. Parts of it have been
    603 	// adapted from userland ctime implementation and other parts
    604 	// have been copied from other parts of the kernel to eliminate
    605 	// dependencies.
    606 	//
    607 	class tod {
    608 	public:
    609 		// Maximum length of a date string including the terminating
    610 		// NULL character returned by ctime_r.
    611 		enum {CTIME_STR_LEN = 32};
    612 
    613 		// Converts seconds since epoch to a printable date string.
    614 		// Adapted from userland ctime_r.
    615 		static char *ctime_r(const time_t *, char *, int);
    616 	private:
    617 #ifdef _KERNEL
    618 		// Represents time of day. Taken from common/sys/time.h.
    619 		typedef struct todinfo {
    620 			int	tod_sec;	// seconds 0-59
    621 			int	tod_min;	// minutes 0-59
    622 			int	tod_hour;	// hours 0-23
    623 			int	tod_dow;	// day of week 1-7
    624 			int	tod_day;	// day of month 1-31
    625 			int	tod_month;	// month 1-12
    626 			int	tod_year;	// year 70+
    627 		} todinfo_t;
    628 
    629 		// Splits seconds since epoch into year, month, day,
    630 		// hours, minutes, seconds.
    631 		// Copied from usr/src/uts/common/os/timers.c
    632 		static todinfo_t utc_to_tod(time_t);
    633 
    634 		// The following methods are supporting methods for ctime_r
    635 		// and have been adapted from their userland counterparts.
    636 		static char *ct_numb(char *, int);
    637 		static char *asctime_r(const todinfo_t *, char *, int);
    638 #endif
    639 	};
    640 
    641 	//
    642 	// miscellaneous library functions
    643 	//
    644 	static int strcmp(const char *s1, const char *s2);
    645 	static int strncmp(const char *s1, const char *s2, size_t n);
    646 	static int strncasecmp(const char *s1, const char *s2, size_t n);
    647 	static char *strcpy(char *dst, const char *src);
    648 	static char *strncpy(char *dst, const char *src, size_t n);
    649 	static char *strstr(const char *s1, const char *s2);
    650 
    651 	static size_t strspn(const char *string, const char *charset);
    652 	static char *strpbrk(const char *string, const char *brkset);
    653 	static char *strtok_r(char *string, const char *sepset, char **lasts);
    654 
    655 	// strdup differs from the normal strdup in two ways:
    656 	// os::strdup allocates memory using "new" and not malloc
    657 	// The returns char * should be freed with delete [] ...
    658 	// os::strdup returns NULL if either string is NULL or
    659 	// the allocation failed (the kernel version does not return NULL)
    660 	static char *strdup(const char *string);
    661 
    662 	static size_t strlen(const char *str);
    663 	static void sprintf(char *buf, const char *fmt, ...);
    664 	static int snprintf(char *buf, size_t n, const char *fmt, ...);
    665 
    666 	static void *bsearch(const void *key, const void *base,
    667 	    size_t nel, size_t size,
    668 	    int (*compar)(const void *, const void *));
    669 
    670 	static void warning(const char *fmt, ...);
    671 	static void printf(const char *fmt, ...);
    672 	static void prom_printf(const char *fmt, ...); // make sure it gets out
    673 	static void abort();
    674 	static void panic(const char *, ...);
    675 	static void log_syslog(const char *fmt, ...);
    676 	static void symtracedump(void);
    677 
    678 	static int cladm(int facility, int command, void *arg);
    679 
    680 	static int create_dir(char *);
    681 	static int rm_dir(char *);
    682 	static int file_link(char *, char *);
    683 	static int file_rename(char *, char *);
    684 	static int file_unlink(char *);
    685 	static int file_copy(char *, char *);
    686 
    687 	// Read-only file stream object
    688 	class rfile {
    689 	public:
    690 		rfile();
    691 		~rfile();
    692 		bool open(char *);
    693 		bool isopen();
    694 		size_t read(char *, size_t, size_t);
    695 		int fgetc();
    696 		int ungetc(int);
    697 		void close();
    698 	private:
    699 #ifdef	_KERNEL
    700 		struct _buf *f;
    701 #else
    702 		FILE *f;
    703 #endif
    704 	};
    705 
    706 	static int mkdirp(const char *path, mode_t mode);
    707 	static int find_unique_subdir(char *path, char *foundpath);
    708 
    709 #ifdef	_KERNEL
    710 	typedef ::dirent64_t dirent_t;
    711 #else
    712 #ifdef linux
    713 	typedef struct dirent dirent_t;
    714 #else
    715 	typedef ::dirent_t dirent_t;
    716 #endif
    717 #endif
    718 
    719 	// os interface for opendir/readdir
    720 	class rdir {
    721 	public:
    722 		rdir();
    723 		~rdir();
    724 		bool open(char *);
    725 		bool isopen();
    726 		dirent_t *read();
    727 		void close();
    728 	private:
    729 #ifdef	_KERNEL
    730 		enum { maxlen = 1024 };	// buffer size
    731 
    732 		vnode_t	*dvp;		// directory vnode
    733 		char *rawdirp;		// buffer for directory contents
    734 		struct dirent64 *nextp;	// pointer to next unread entry
    735 		struct dirent64 *lastp;	// pointer to last entry in rawdirp
    736 		offset_t doff;		// directory offset to read from
    737 #else
    738 		DIR *d;
    739 #endif
    740 	};
    741 
    742 	// translate a string decimal internet address to a inaddr_t
    743 	// NOTE: This function behaves differently than
    744 	// the user-level library function inet_addr
    745 	static in_addr_t inet_addr(const char *);
    746 
    747 	// sc_syslog_msg interfaces
    748 
    749 	//
    750 	// The method calls in turn invoke openlog(3) and syslog(3) in
    751 	// user-land and cmn_err(9F) in kernel-land.
    752 	// The second parameter to openlog(3) viz. logopt cannot be specified
    753 	// when invoking methods of sc_syslog_msg class. It is always set
    754 	// to LOG_CONS by methods in sc_syslog_msg class.
    755 	//
    756 	// Other parameters to openlog(3) such as ident (1st parameter)
    757 	// can be specified in the constructor
    758 	// of sc_syslog_msg class for user-land modules.
    759 	// facility is always set to LOG_DAEMON for user-land modules.
    760 	//
    761 
    762 	class sc_syslog_msg {
    763 	public:
    764 		//
    765 		// Constructor
    766 		//
    767 		// Paramters:
    768 		//
    769 		// resource_type_specific_tag -
    770 		// 	This tag will become part of the message id. of the
    771 		//	logged message.
    772 		//	- It should not be NULL.
    773 		//	- Some resource_type_specific_tags
    774 		//	  are defined in sc_syslog_msg.h
    775 		//
    776 		// resource_name -
    777 		//	resource_type_specific_tag and resource_name are
    778 		//	concatenated to create the <message tag> part of the
    779 		//	message id.
    780 		//	- It should not be NULL.
    781 		//	- It should be unique clusterwide.
    782 		//	  For example, if it is a message logged by CMM for
    783 		//	  node 2, resource_name should be "2".
    784 		//
    785 		//
    786 
    787 		sc_syslog_msg(
    788 			const char 	*resource_type_specific_tag,
    789 			const char	*resource_name,
    790 			void		*);
    791 
    792 		//
    793 		// log() - Logs a message with the syslog facility
    794 		//
    795 		// Paramters:
    796 		//
    797 		// priority - priority of the logged message. see syslog(3)
    798 		//		or cmn_err(9F) for additional information.
    799 		//		Some common priority values are defined in
    800 		//		sc_syslog_msg.h to avoid having to put ifdefs
    801 		//		in the code that is shared in kernel and
    802 		//		user-land.
    803 		//
    804 		// format - Formatted message as it is logged using syslog(3)
    805 		//		or cmn_err(9F)
    806 		//
    807 		//
    808 		sc_syslog_msg_status_t log(
    809 			int		priority,
    810 			sc_event_type_t	event_type,
    811 			const char	*format,
    812 			...);
    813 
    814 		~sc_syslog_msg();
    815 private:
    816 		sc_syslog_msg_handle_t	msg_handle;
    817 
    818 		// Disallow assignments and pass by value
    819 		sc_syslog_msg(const sc_syslog_msg &);
    820 		sc_syslog_msg &operator = (sc_syslog_msg &);
    821 	}; // end of sc_syslog_msg
    822 
    823 	//
    824 	// class systime
    825 	//
    826 	// Simple class for dealing with system time.
    827 	class systime {
    828 		friend class condvar_t;
    829 	public:
    830 		// constructor
    831 		systime(usec_t offset = 0);
    832 
    833 		// Set the time of this object to some offset relative to now.
    834 		void setreltime(usec_t offset);
    835 
    836 		// Is this time in the past.
    837 		bool is_past();
    838 
    839 		// Is this time in the future.
    840 		bool is_future();
    841 
    842 		// Is this time before that.
    843 		bool is_before(systime &);
    844 
    845 		// Set the time.
    846 		void set(systime &);
    847 
    848 	private:
    849 #ifdef	_KERNEL
    850 		long		_time;
    851 #else	// _KERNEL
    852 		timestruc_t	_time;
    853 #endif	// _KERNEL
    854 
    855 		// Disallow assignments and pass by value
    856 		systime(const systime &);
    857 		systime &operator = (systime &);
    858 	};
    859 
    860 	//
    861 	// class ctype
    862 	//
    863 	// simple routines for deriving character types
    864 	//
    865 	// NB: For the kernel these are optimized since they
    866 	// need not perform internationalization.
    867 	// The userland versions map directly to libc.
    868 	//
    869 	// This list isn't complete, but contains the methods
    870 	// we currently use in the kernel.
    871 	//
    872 	// Since the is* functions are macros, we cannot simply
    873 	// map the names one for one (they're all expanded inline).
    874 	// Given that limitation, we've added an underscore.
    875 	//
    876 	class ctype {
    877 	public:
    878 		static int is_digit(int c);
    879 		static int is_alpha(int c);
    880 		static int is_xdigit(int c);
    881 		static int is_upper(int c);
    882 		static int is_lower(int c);
    883 		static int is_space(int c);
    884 	};
    885 
    886 	static int atoi(const char *str);
    887 
    888 	// Convert int to char *. Caller needs to make sure
    889 	// the space pointed by char * is big enough. It returns the
    890 	// number of digits copied.
    891 	static int itoa(int, char *, uint_t base = 10);
    892 
    893 	//
    894 	// Find highest and lowest one bit set.
    895 	//	Returns bit number + 1 of bit that is set, otherwise returns 0.
    896 	// Low order bit is 0, high order bit is 31.
    897 	//
    898 	static int highbit(ulong_t);
    899 	static int lowbit(ulong_t);
    900 
    901 	//
    902 	// copyin - replace with a bcopy function call and a sequence
    903 	// operator (the comma) followed by the return value of success.
    904 	// The unode copyin has no problems crossing from user to kernel space.
    905 	//
    906 	// copyout - replace with a bcopy function call and a sequence
    907 	// operator (the comma) followed by the return value of success.
    908 	// The unode copyout has no problems crossing from kernel to user space.
    909 	//
    910 #ifndef _KERNEL
    911 	static int copyin(const void *src, void *dest, size_t size)
    912 	    { bcopy(src, dest, size); return (0); }
    913 	static int x_copyin(const void *src, void *dest, size_t size)
    914 	    { bcopy(src, dest, size); return (0); }
    915 	static int copyout(const void *src, void *dest, size_t size)
    916 	    { bcopy(src, dest, size); return (0); }
    917 	static int x_copyout(const void *src, void *dest, size_t size)
    918 	    { bcopy(src, dest, size); return (0); }
    919 	static int copyoutstr(const void *src, void *dest, size_t,
    920 	    size_t *lencopied)
    921 	    { *(lencopied) = strlen((const char *)src);
    922 		bcopy(src, dest, *(lencopied)); return (0); }
    923 #else
    924 	static int copyin(const void *src, void *dest, size_t size)
    925 	    { return (::copyin(src, dest, size)); }
    926 	static int x_copyin(const void *src, void *dest, size_t size)
    927 	    { return (::xcopyin(src, dest, size)); }
    928 	static int copyout(const void *src, void *dest, size_t size)
    929 	    { return (::copyout(src, dest, size)); }
    930 	static int x_copyout(const void *src, void *dest, size_t size)
    931 	    { return (::xcopyout(src, dest, size)); }
    932 	static int copyoutstr(const void *src, void *dest, size_t size,
    933 	    size_t *lencopied) {
    934 		return (::copyoutstr((const char *)src, (char *)dest, size,
    935 		lencopied));
    936 	    }
    937 #endif
    938 	//
    939 	// str2sig() only exists on Solaris.  On Linux, we need to
    940 	// provide our own implementation.
    941 	//
    942 	static int str2sig(const char *s, int *sigp);
    943 
    944 	// Abstraction of getnetbyname_r()
    945 	static struct netent *getnetbyname_r(const char *name,
    946 	    struct netent *result_buf, char *buffer, int *res);
    947 	// Abstraction of getrpcbyname_r()
    948 	static struct rpcent *getrpcbyname_r(const char *name,
    949 		struct rpcent *result_buf, char *buffer, int buflen);
    950 
    951 private:
    952 
    953 #ifdef _KERNEL_ORB
    954 	// Used by usecsleep()
    955 	static mutex_t		sleep_mutex;
    956 	static condvar_t	sleep_cv;
    957 #endif
    958 
    959 }; // class os
    960 
    961 void *shared_new(size_t, os::mem_alloc_type, os::mem_zero_type);
    962 
    963 //
    964 // In a 32-bit kernel, size_t is defined as an unsigned long.  But the
    965 // C++ compiler "knows" that size_t is an unsigned int, so if we define
    966 // new operators using size_t we'll get compilation errors.  So we use
    967 // galsize_t when defining new and delete operators.  Everywhere else
    968 // we use size_t.
    969 //
    970 #if defined(_LP64) || !defined(_I32LPx)
    971 typedef size_t galsize_t;
    972 #else
    973 typedef uint_t galsize_t;
    974 #endif
    975 
    976 #ifdef	_KERNEL
    977 
    978 // If inlines are disabled (and won't be seen by including os_in.h)
    979 // we need prototypes for the forms of operator new().
    980 
    981 #ifdef NOINLINES
    982 void *operator new(galsize_t, os::mem_zero_type);
    983 void *operator new(galsize_t, os::mem_alloc_type);
    984 void *operator new(galsize_t, os::mem_alloc_type, os::mem_zero_type);
    985 #endif
    986 
    987 // id for "not a thread"
    988 // Disabling this as this results in 1 variable instance per .cc file!
    989 // const os::threadid_t NO_THREAD = NULL;
    990 
    991 #else	// _KERNEL
    992 
    993 #ifdef NOINLINES
    994 void *operator new(size_t, os::mem_zero_type);
    995 void *operator new(size_t, os::mem_alloc_type);
    996 void *operator new(size_t, os::mem_alloc_type, os::mem_zero_type);
    997 
    998 #endif
    999 
   1000 // id for "not a thread"
   1001 const os::threadid_t NO_THREAD = 0;
   1002 
   1003 extern os::mutex_t atomic_lock[ATOMIC_HASH_SIZE];
   1004 
   1005 #endif	// _KERNEL
   1006 
   1007 #include <sys/knewdel.h>
   1008 
   1009 // If inlines are enabled the _in.h headers are included here,
   1010 // otherwise non-inline methods are built into libkos/libuos
   1011 // (see os_misc.cc).
   1012 
   1013 #ifndef NOINLINES
   1014 #include <sys/os_in.h>
   1015 
   1016 #ifdef DEBUGGER_PRINT
   1017 #include <dbg_os_in.h>
   1018 inline void *
   1019 /*CSTYLED*/
   1020 operator new[](galsize_t len, os::mem_alloc_type flag)
   1021 {
   1022 	extern void *shared_new(size_t, os::mem_alloc_type, os::mem_zero_type);
   1023 
   1024 	return (shared_new((size_t)len, flag, os::DONTZERO));
   1025 }
   1026 #else
   1027 #ifdef 	_KERNEL
   1028 #include <sys/kos_in.h>
   1029 #else	// _KERNEL
   1030 #include <sys/uos_in.h>
   1031 #endif	// _KERNEL
   1032 #endif // DEBUGGER_PRINT
   1033 
   1034 #endif	// _NOINLINES
   1035 
   1036 #else /* __cplusplus */
   1037 
   1038 /*
   1039  * OS dependent functions needed for C programs
   1040  */
   1041 #ifdef linux
   1042 extern int mkdirp(const char *path, mode_t mode);
   1043 extern hrtime_t gethrtime();
   1044 extern struct hostent *getipnodebyname(const char *name, int af,
   1045 	int flags, int *error_num);
   1046 extern void freehostent(struct hostent *hp);
   1047 #endif
   1048 
   1049 #endif /* __cplusplus */
   1050 
   1051 #ifdef __cplusplus
   1052 extern "C" {
   1053 #endif
   1054 
   1055 #ifdef __cplusplus
   1056 }
   1057 #endif
   1058 
   1059 #endif	/* _OS_H */
   1060