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/OPENSOLARIS.LICENSE 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/OPENSOLARIS.LICENSE. 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# Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23# Use is subject to license terms. 24# 25 26# Process Model Unification 27 28The Solaris Process Model Unification project: 29 PSARC/2002/117 Solaris Process Model Unification 30 4470917 Solaris Process Model Unification 31folded libthread into libc and has led to some fundamental changes 32in the rules by which code in libc must be developed and maintained. 33 34All code in libc must be both MT-Safe and Fork-Safe 35and where possible (almost everywhere), Async-Signal-Safe. 36 37To this end, the following rules should be followed: 38 39Almost all internal libc locks (mutexes and read-write locks) 40should be acquired and released via these interfaces: 41 42 mutex_t some_lock = DEFAULTMUTEX; 43 44 lmutex_lock(&some_lock); 45 ... do something critical ... 46 lmutex_unlock(&some_lock); 47 48 rwlock_t some_rw_lock = DEFAULTRWLOCK; 49 50 lrw_rdlock(&some_rw_lock); 51 ... multiple threads can do something ... 52 lrw_unlock(&some_rw_lock); 53 54 lrw_wrlock(&some_rw_lock); 55 ... only one thread can do something ... 56 lrw_unlock(&some_rw_lock); 57 58The above l* versions of the mutex and rwlock interfaces do more 59than the ordinary interfaces: They define critical regions in 60which the calling thread cannot be suspended (making the region 61fork-safe) and in which the calling thread has all signals deferred 62(making the region async-signal-safe). 63 64However, certain rules apply to the code within these critical regions: 65 66 - The code must be of guaranteed short duration; no calls 67 to interfaces that might block indefinitely are allowed. 68 This means no calls into stdio or syslog() and no calls 69 to cond_wait() unless there is a guarantee of an almost- 70 immediate call to cond_signal() or cond_broadcast() 71 from elsewhere. 72 73 - The code cannot call any non-l* synchronization 74 primitives (mutex_lock(), _private_mutex_lock(), 75 rw_wrlock(), rw_rdlock(), sema_wait(), etc.) 76 77 - The code cannot call any functions outside of libc, 78 including application callbacks and functions from 79 dlopen()ed objects, such as those in the I18N code. 80 81 - Because malloc(), calloc(), realloc(), and free() 82 are designed to be interposed upon, they fall into 83 the previous case of prohibition. None of these can 84 be called by a thread while in a critical region. 85 86There is a private memory allocator for use internally to libc. 87It cannot be interposed upon and it is safe to use while in 88a critical region (or for that matter while not in a critical 89region; it is async-signal-safe and fork-safe): 90 91 void *lmalloc(size_t); 92 void lfree(void *, size_t); 93 94 void *libc_malloc(size_t); 95 void *libc_realloc(void *, size_t); 96 char *libc_strdup(const char *); 97 void libc_free(void *); 98 99lmalloc() and lfree() are the basic interfaces. The libc_*() 100variants are built on top of lmalloc()/lfree() but they have 101the same interface signatures as the corresponding functions 102without the 'libc_' prefix. lmalloc() and libc_malloc() 103return zeroed memory blocks. Note that lmalloc()/lfree() 104require the caller to remember the size parameter passed 105to lmalloc() and to pass the same value to lfree(). 106 107Memory allocated by lmalloc() can only be freed by lfree(). 108Memory allocated by libc_malloc(), libc_realloc(), or libc_strdup() 109can only be freed by libc_free(). Never pass such allocated 110memory out of libc if the caller of libc is expected to free it. 111 112lmalloc()/lfree() is a small and simple power of two allocator. 113Do not use it as a general-purpose allocator. Be kind to it. 114 115There is a special mutual exclusion interface that exists for 116cases, like code in the I18N interfaces, where mutual exclusion 117is required but the above rules cannot be followed: 118 119 int fork_lock_enter(const char *); 120 void fork_lock_exit(void); 121 122fork_lock_enter() does triple-duty. Not only does it serialize 123calls to fork() and forkall(), but it also serializes calls to 124thr_suspend() (fork() and forkall() also suspend other threads), 125and furthermore it serializes I18N calls to functions in other 126dlopen()ed L10N objects that might be calling malloc()/free(). 127Use it in general like this: 128 129 (void) fork_lock_enter(NULL); 130 ... serialized; do something that might call malloc ... 131 fork_lock_exit(); 132 133The 'const char *' argument to fork_lock_enter() should always 134be NULL except for two special cases: 135 - When called from fork() or forkall() 136 - When called from pthread_atfork() 137This enforces the prohibition against calling fork() or pthread_atfork() 138from a pthread_atfork()-registered fork handler function while a fork() 139prologue or epilogue is in progress. If _THREAD_ERROR_DETECTION is set 140to 1 or 2 in the environment, such cases will draw a nasty message and 141will dump core if _THREAD_ERROR_DETECTION=2. fork_lock_enter() returns 142non-zero only if it is called from a fork handler. This is of interest 143only to callers that have to do something about this condition; the 144return value should be ignored in all other cases (fork_lock_enter() 145never actually fails). 146 147It is an error to call fork_lock_enter() while in a critical region 148(that is, while holding any internal libc lock). 149 150On return from fork_lock_enter(), no internal libc locks are held 151but a flag has been set to cause other callers of fork_lock_enter() 152to delay (via _cond_wait()) until fork_lock_exit() is called. 153 154These are the rules to follow for memory allocation: 155 156 - If a function acquires an internal libc lock or is called while 157 an internal libc lock is held: 158 159 * The malloc family cannot be used. 160 161 * lmalloc or libc_malloc should be used. The memory must 162 be released by lfree or libc_free, respectively. 163 164 * lfree takes an argument to tell the size of the releasing 165 memory. If the function does not know the size at the 166 releasing point, libc_malloc and libc_free should be used. 167 168 * As the memory allocated by lmalloc or libc_malloc needs 169 to be released by lfree or libc_free and these are internal 170 to libc, they cannot be used to allocate memory that might 171 be released by application code outside libc. 172 173 * If the memory allocation by malloc() cannot be avoided and 174 the scalability of the function does not matter much, the 175 function can be serialized with fork_lock_enter() instead 176 of lmutex_lock(). 177 178 * If the memory allocation by malloc() cannot be avoided and 179 the scalability of the function does matter, another 180 implementation of the function will be necessary. 181 182In a DEBUG build of libc: 183 make THREAD_DEBUG=-DTHREAD_DEBUG install 184many of these rules are enforced by ASSERT() statements scattered about 185in the libc sources. This is the default mode for building libc when 186a DEBUG nightly build is performed. 187 188# libaio/librt Implementation In libc 189 190The putback of the project: 191 6416832 libaio and librt can and should be folded into libc 192introduced several libc-private locking interfaces: 193 void sig_mutex_lock(mutex_t *); 194 void sig_mutex_unlock(mutex_t *); 195 int sig_mutex_trylock(mutex_t *); 196 int sig_cond_wait(cond_t *, mutex_t *); 197 int sig_cond_reltimedwait(cond_t *, mutex_t *, const timespec_t *); 198which are declared in both "thr_uberdata.h" and "mtlib.h". 199 200They are used in specialized code in libc, like the asynchronous i/o code. 201Unlike the lmutex_lock() and lmutex_unlock() interfaces described above, 202these interfaces do not define critical regions, but signals are 203deferred while locks acquired by these functions are held, making 204their use be async-signal safe. Calls to malloc(), calloc(), realloc(), 205and free() are permissible while holding such locks. 206 207These interfaces were brought over from code in the former libaio 208and librt and are necessary because, where they are used, the code 209must execute potentially long-term waits and must be cancelable. 210sig_cond_wait() and sig_cond_reltimedwait() are cancellation points. 211 212These interfaces are available for other uses inside libc, as 213the need arises. (There is no need if the code does not perform 214long-term waits.) Just follow a few rules to be self-consistent: 215 - Don't mix calls to mutex_[un]lock(), lmutex_[un]lock() and 216 sig_mutex_[un]lock() on the same mutex. 217 - Don't call cond_wait() with a mutex acquired by sig_mutex_lock(); 218 call sig_cond_wait() or sig_cond_reltimedwait(). 219 - Use pthread_cleanup_push() and pthread_cleanup_pop() to make 220 your code cancellation-safe. 221 - The sig_*() interfaces are not in themselves fork-safe. 222 You have to employ other logic to make your code fork-safe. 223 See the tail of postfork1_child() for examples. 224 225# Removal Of Synonym Symbols 226 227The following project: 228 PSARC 2008/309 expunge synonyms.h 229 6700179 expunge synonyms.h 230 231Removed the historical "synonym" symbols from the C Library. 232 233Historically, for every public function symbol in the C library a second, 234private, symbol of the same value was defined to be used internally by libc 235(generally, one or the other will be a weak symbol, precisely which is 236inconsistent). 237 238These synonym symbols existed such that an application which provided 239otherwise conflicting symbols could interpose on the version in libc without 240compromising libc itself, that is if libc defines fopen() which needs open() it 241would call _open() and an application defined open() would not cause fopen() 242to break. This was made transparent to code within libc via a header, 243synonyms.h, which would #define open _open, for all such symbols. 244 245Since ON now uses direct bindings extensively all symbols not explicitly 246marked "NODIRECT" are directly bound within libc anyway, and none of this is 247actually necessary. Thus synonyms.h was removed, and no new synonym symbols 248need be added. However, unfortunately, certain of the private symbols were 249inadvertently exposed to applications, and several are known to have been 250used, thus these existing synonyms must continue to exist to maintain 251compatibility. A preloadable library, /lib/c_synonyms.so.1 is provided which 252also provides the historical names with underscore prefixes to allow any other 253incorrect application to continue to function. 254 255It should never be necessary to add additional synonym symbols to libc nor to 256add underscore prefixed aliases to c_synonyms.so.1. 257 258# libc Internals Scoped Protected 259 260The integration of the fix for: 261 6689238 libc needs global protection against ld.so.1 262 263Scopes all function symbols within libc protected, excepting those that need 264to be accepting of interposition and to have a consistent version called both 265within and without libc (basically, the malloc() family). 266 267This causes references by libc to itself to be permanently and unavoidably 268bound, and thus to never enter ld.so (and potentially from there audit 269libraries or other such support libraries). This maintains an otherwise 270complicated to verify invariant: within critical sections (with any internal 271lock held, etc) execution can never leave the context of libc. Previously 272this was done with a selection of known-to-be-problematic functions having 273weak synonyms scoped private, but this was both difficult to verify, difficult 274to remember, and thus always at least somewhat incomplete. 275 276In summary, any new function symbol in libc must be scoped protected unless it 277is one of a very small group of functions that must allow interposed versions 278to be bound to from the C library itself -- it is grossly unlikely that more 279of these will occur. 280