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, Version 1.0 only 6# (the "License"). You may not use this file except in compliance 7# with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# 23# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26# ident "%Z%%M% %I% %E% SMI" 27# 28 29The Solaris Process Model Unification project: 30 PSARC/2002/117 Solaris Process Model Unification 31 4470917 Solaris Process Model Unification 32folded libthread into libc and has led to some fundamental changes 33in the rules by which code in libc must be developed and maintained. 34 35All code in libc must be both MT-Safe and Fork-Safe 36and where possible (almost everywhere), Async-Signal-Safe. 37 38To this end, the following rules should be followed: 39 40Almost all internal libc locks (mutexes and read-write locks) 41should be acquired and released via these interfaces: 42 43 mutex_t some_lock = DEFAULTMUTEX; 44 45 lmutex_lock(&some_lock); 46 ... do something critical ... 47 lmutex_unlock(&some_lock); 48 49 rwlock_t some_rw_lock = DEFAULTRWLOCK; 50 51 lrw_rdlock(&some_rw_lock); 52 ... multiple threads can do something ... 53 lrw_unlock(&some_rw_lock); 54 55 lrw_wrlock(&some_rw_lock); 56 ... only one thread can do something ... 57 lrw_unlock(&some_rw_lock); 58 59The above l* versions of the mutex and rwlock interfaces do more 60than the ordinary interfaces: They define critical regions in 61which the calling thread cannot be suspended (making the region 62fork-safe) and in which the calling thread has all signals deferred 63(making the region async-signal-safe). 64 65However, certain rules apply to the code within these critical regions: 66 67 - The code must be of guaranteed short duration; no 68 calls to interfaces that might block indefinitely are 69 allowed. This means no calls into stdio or syslog(). 70 71 - The code cannot call any non-l* synchronization 72 primitives (mutex_lock(), _private_mutex_lock(), 73 rw_wrlock(), rw_rdlock(), sema_wait(), etc.) 74 75 - The code cannot call any functions outside of libc, 76 including application callbacks and functions from 77 dlopen()ed objects, such as those in the I18N code. 78 79 - Because malloc(), calloc(), realloc(), and free() 80 are designed to be interposed upon, they fall into 81 the previous case of prohibition. None of these can 82 be called by a thread while in a critical region. 83 84There is a private memory allocator for use internally to libc. 85It cannot be interposed upon and it is safe to use while in 86a critical region (or for that matter while not in a critical 87region; it is async-signal-safe and fork-safe): 88 89 void *lmalloc(size_t); 90 void lfree(void *, size_t); 91 92 void *libc_malloc(size_t); 93 void *libc_realloc(void *, size_t); 94 char *libc_strdup(const char *); 95 void libc_free(void *); 96 97lmalloc() and lfree() are the basic interfaces. The libc_*() 98variants are built on top of lmalloc()/lfree() but they have 99the same interface signatures as the corresponding functions 100without the 'libc_' prefix. lmalloc() and libc_malloc() 101return zeroed memory blocks. Note that lmalloc()/lfree() 102require the caller to remember the size parameter passed 103to lmalloc() and to pass the same value to lfree(). 104 105Memory allocated by lmalloc() can only be freed by lfree(). 106Memory allocated by libc_malloc(), libc_realloc(), or libc_strdup() 107can only be freed by libc_free(). Never pass such allocated 108memory out of libc if the caller of libc is expected to free it. 109 110lmalloc()/lfree() is a small and simple power of two allocator. 111Do not use it as a general-purpose allocator. Be kind to it. 112 113There is a special mutual exclusion interface that exists for 114cases, like code in the I18N interfaces, where mutual exclusion 115is required but the above rules cannot be followed: 116 117 int fork_lock_enter(const char *); 118 void fork_lock_exit(void); 119 120fork_lock_enter() does triple-duty. Not only does it serialize 121calls to fork() and forkall(), but it also serializes calls to 122thr_suspend() (fork() and forkall() also suspend other threads), 123and furthermore it serializes I18N calls to functions in other 124dlopen()ed L10N objects that might be calling malloc()/free(). 125Use it in general like this: 126 127 (void) fork_lock_enter(NULL); 128 ... serialized; do something that might call malloc ... 129 fork_lock_exit(); 130 131The 'const char *' argument to fork_lock_enter() should always 132be NULL except for two special cases: 133 - When called from fork() or forkall() 134 - When called from pthread_atfork() 135This enforces the prohibition against calling fork() or pthread_atfork() 136from a pthread_atfork()-registered fork handler function while a fork() 137prologue or epilogue is in progress. If _THREAD_ERROR_DETECTION is set 138to 1 or 2 in the environment, such cases will draw a nasty message and 139will dump core if _THREAD_ERROR_DETECTION=2. fork_lock_enter() returns 140non-zero only if it is called from a fork handler. This is of interest 141only to callers that have to do something about this condition; the 142return value should be ignored in all other cases (fork_lock_enter() 143never actually fails). 144 145It is an error to call fork_lock_enter() while in a critical region 146(that is, while holding any internal libc lock). 147 148On return from fork_lock_enter(), no internal libc locks are held 149but a flag has been set to cause other callers of fork_lock_enter() 150to delay (via _cond_wait()) until fork_lock_exit() is called. 151 152These are the rules to follow for memory allocation: 153 154 - If a function acquires an internal libc lock or is called while 155 an internal libc lock is held: 156 157 * The malloc family cannot be used. 158 159 * lmalloc or libc_malloc should be used. The memory must 160 be released by lfree or libc_free, respectively. 161 162 * lfree takes an argument to tell the size of the releasing 163 memory. If the function does not know the size at the 164 releasing point, libc_malloc and libc_free should be used. 165 166 * As the memory allocated by lmalloc or libc_malloc needs 167 to be released by lfree or libc_free and these are internal 168 to libc, they cannot be used to allocate memory that might 169 be released by application code outside libc. 170 171 * If the memory allocation by malloc() cannot be avoided and 172 the scalability of the function does not matter much, the 173 function can be serialized with fork_lock_enter() instead 174 of lmutex_lock(). 175 176 * If the memory allocation by malloc() cannot be avoided and 177 the scalability of the function does matter, another 178 implementation of the function will be necessary. 179 180In a DEBUG build of libc: 181 make THREAD_DEBUG=-DTHREAD_DEBUG install 182many of these rules are enforced by ASSERT() statements scattered about 183in the libc sources. This is the default mode for building libc when 184a DEBUG nightly build is performed. 185 186----- 187 188Some i18n code cannot be distributed as open source. To enable the rest of 189libc to be distributed as open source, those i18n files now live in a 190separate libc_i18n directory. Those source files are position-independently 191compiled and are archived into the libc_i18n.a library. The libc_i18n.a 192archive library is installed into the $(ROOTFS_LIBDIR) and 193$(ROOTFS_LIBDIR64) directories. During link phase, libc.so.1 links with 194libc_i18n.a in the proto area. Therefore, the build of the libc_i18n tree 195needs to be done before the build of the libc tree. Also the compilation 196conditions such as the setting of CFLAGS and CPPFLAGS for the libc_i18n 197stuff need to be compatible with the ones for the libc stuff. Whenever 198changes that affect the compilation conditions of libc occur, the changes 199should be propagated to libc_i18n. 200