Print this page
OS-5192 need faster clock_gettime
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Joshua M. Clulow <jmc@joyent.com>
Reviewed by: Ryan Zezeski <ryan@zinascii.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/sgs/rtld/common/external.c
+++ new/usr/src/cmd/sgs/rtld/common/external.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
25 - * Copyright 2015 Joyent, Inc.
25 + * Copyright 2016 Joyent, Inc.
26 26 */
27 27
28 28 /*
29 29 * Implementation of all external interfaces between ld.so.1 and libc.
30 30 *
31 31 * This file started as a set of routines that provided synchronization and
32 32 * locking operations using calls to libthread. libthread has merged with libc
33 33 * under the Unified Process Model (UPM), and things have gotten a lot simpler.
34 34 * This file continues to establish and redirect various events within ld.so.1
35 35 * to interfaces within libc.
36 36 *
37 37 * Until libc is loaded and relocated, any external interfaces are captured
38 38 * locally. Each link-map list maintains its own set of external vectors, as
39 39 * each link-map list typically provides its own libc. Although this per-link-
40 40 * map list vectoring provides a degree of flexibility, there is a protocol
41 41 * expected when calling various libc interfaces.
42 42 *
43 43 * i. Any new alternative link-map list should call CI_THRINIT, and then call
44 44 * CI_TLS_MODADD to register any TLS for each object of that link-map list
45 45 * (this item is labeled i. as auditors can be the first objects loaded,
46 46 * and they exist on their own lik-map list).
47 47 *
48 48 * ii. For the primary link-map list, CI_TLS_STATMOD must be called first to
49 49 * register any static TLS. This routine is called regardless of there
50 50 * being any TLS, as this routine also establishes the link-map list as the
51 51 * primary list and fixes the association of uberdata). CI_THRINIT should
52 52 * then be called.
53 53 *
54 54 * iii. Any objects added to an existing link-map list (primary or alternative)
55 55 * should call CI_TLS_MODADD to register any additional TLS.
56 56 *
57 57 * These events are established by:
58 58 *
59 59 * i. Typically, libc is loaded as part of the primary dependencies of any
60 60 * link-map list (since the Unified Process Model (UPM), libc can't be
61 61 * lazily loaded). To minimize the possibility of loading and registering
62 62 * objects, and then tearing them down (because of a relocation error),
63 63 * external vectors are established as part of load_completion(). This
64 64 * routine is called on completion of any operation that can cause objects
65 65 * to be loaded. This point of control insures the objects have been fully
66 66 * analyzed and relocated, and moved to their controlling link-map list.
67 67 * The external vectors are established prior to any .inits being fired.
68 68 *
69 69 * ii. Calls to CI_THRINIT, and CI_TLS_MODADD also occur as part of
70 70 * load_completion(). CI_THRINIT is only called once for each link-map
71 71 * control list.
72 72 *
73 73 * iii. Calls to CI_TLS_STATMOD, and CI_THRINIT occur for the primary link-map
74 74 * list in the final stages of setup().
75 75 *
76 76 * The interfaces provide by libc can be divided into two families. The first
77 77 * family consists of those interfaces that should be called from the link-map
78 78 * list. It's possible that these interfaces convey state concerning the
79 79 * link-map list they are part of:
80 80 *
81 81 * CI_ATEXIT
82 82 * CI TLS_MODADD
83 83 * CI_TLS_MODREM
84 84 * CI_TLS_STATMOD
85 85 * CI_THRINIT
86 86 *
87 87 * The second family are global in nature, that is, the link-map list from
88 88 * which they are called provides no state information. In fact, for
89 89 * CI_BIND_GUARD, the calling link-map isn't even known. The link-map can only
90 90 * be deduced after ld.so.1's global lock has been obtained. Therefore, the
91 91 * following interfaces are also maintained as global:
92 92 *
93 93 * CI_LCMESSAGES
94 94 * CI_BIND_GUARD
95 95 * CI_BIND_CLEAR
96 96 * CI_THR_SELF
97 97 *
98 98 * Note, it is possible that these global interfaces are obtained from an
99 99 * alternative link-map list that gets torn down because of a processing
100 100 * failure (unlikely, because the link-map list components must be analyzed
101 101 * and relocated prior to load_completion(), but perhaps the tear down is still
102 102 * a possibility). Thus the global interfaces may have to be replaced. Once
103 103 * the interfaces have been obtained from the primary link-map, they can
104 104 * remain fixed, as the primary link-map isn't going to go anywhere.
105 105 *
106 106 * The last wrinkle in the puzzle is what happens if an alternative link-map
107 107 * is loaded with no libc dependency? In this case, the alternative objects
108 108 * can not call CI_THRINIT, can not be allowed to use TLS, and will not receive
109 109 * any atexit processing.
110 110 *
111 111 * The history of these external interfaces is defined by their version:
112 112 *
113 113 * TI_VERSION == 1
114 114 * Under this model libthread provided rw_rwlock/rw_unlock, through which
115 115 * all rt_mutex_lock/rt_mutex_unlock calls were vectored.
116 116 * Under libc/libthread these interfaces provided _sigon/_sigoff (unlike
117 117 * lwp/libthread that provided signal blocking via bind_guard/bind_clear).
118 118 *
119 119 * TI_VERSION == 2
120 120 * Under this model only libthreads bind_guard/bind_clear and thr_self
121 121 * interfaces were used. Both libthreads blocked signals under the
122 122 * bind_guard/bind_clear interfaces. Lower level locking is derived
123 123 * from internally bound _lwp_ interfaces. This removes recursive
124 124 * problems encountered when obtaining locking interfaces from libthread.
125 125 * The use of mutexes over reader/writer locks also enables the use of
126 126 * condition variables for controlling thread concurrency (allows access
127 127 * to objects only after their .init has completed).
128 128 *
129 129 * NOTE, the TI_VERSION indicated the ti_interface version number, where the
130 130 * ti_interface was a large vector of functions passed to both libc (to override
131 131 * the thread stub interfaces) and ld.so.1. ld.so.1 used only a small subset of
132 132 * these interfaces.
133 133 *
134 134 * CI_VERSION == 1
135 135 * Introduced with CI_VERSION & CI_ATEXIT
136 136 *
137 137 * CI_VERSION == 2 (Solaris 8 update 2).
138 138 * Added support for CI_LCMESSAGES
139 139 *
140 140 * CI_VERSION == 3 (Solaris 9).
141 141 * Added the following versions to the CI table:
142 142 *
143 143 * CI_BIND_GUARD, CI_BIND_CLEAR, CI_THR_SELF
144 144 * CI_TLS_MODADD, CI_TLS_MOD_REMOVE, CI_TLS_STATMOD
145 145 *
146 146 * This version introduced the DT_SUNW_RTLDINFO structure as a mechanism
147 147 * to handshake with ld.so.1.
148 148 *
149 149 * CI_VERSION == 4 (Solaris 10).
150 150 * Added the CI_THRINIT handshake as part of the libc/libthread unified
151 151 * process model. libc now initializes the current thread pointer from
152 152 * this interface (and no longer relies on the INITFIRST flag - which
153 153 * others have started to camp out on).
154 154 *
155 155 * CI_VERSION == 5 (Solaris 11).
156 156 * Use of "protected" references within libc, so that symbols are
157 157 * pre-bound, and don't require ld.so.1 binding. This implementation
158 158 * protects libc's critical regions from being vectored to auditors.
159 159 *
160 160 * CI_VERSION == 6 (Solaris 11).
161 161 * Added the CI_CRITICAL handshake, to allow "mem*" family to be reexposed
162 162 * as "global", and thus be redirected to auxiliary filters.
163 163 *
164 164 * Release summary:
165 165 *
166 166 * Solaris 8 CI_ATEXIT via _ld_libc()
167 167 * TI_* via _ld_concurrency()
168 168 *
169 169 * Solaris 9 CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
170 170 * CI_* via RTLDINFO and _ld_libc() - new libthread
171 171 * TI_* via _ld_concurrency() - old libthread
172 172 *
173 173 * Solaris 10 CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
174 174 * CI_* via RTLDINFO and _ld_libc() - new libthread
175 175 */
176 176
177 177 #include <sys/debug.h>
178 178 #include <synch.h>
179 179 #include <signal.h>
180 180 #include <thread.h>
181 181 #include <synch.h>
182 182 #include <strings.h>
183 183 #include <stdio.h>
184 184 #include <libintl.h>
185 185 #include <debug.h>
186 186 #include <libc_int.h>
187 187 #include "_elf.h"
188 188 #include "_rtld.h"
189 189
190 190 /*
191 191 * This interface provides the unified process model communication between
192 192 * ld.so.1 and libc. This interface can be called a number of times:
193 193 *
194 194 * - Initially, this interface is called to process RTLDINFO. This data
195 195 * structure is typically provided by libc, and contains the address of
196 196 * libc interfaces that must be called to initialize threads information.
197 197 *
198 198 * - _ld_libc(), this interface can also be called by libc at process
199 199 * initialization, after libc has been loaded and relocated, but before
200 200 * control has been passed to any user code (.init's or main()). This
201 201 * call provides additional libc interface information that ld.so.1 must
202 202 * call during process execution.
203 203 *
204 204 * - _ld_libc() can also be called by libc during process execution to
205 205 * re-establish interfaces such as the locale.
206 206 */
207 207 static void
208 208 get_lcinterface(Rt_map *lmp, Lc_interface *funcs)
209 209 {
210 210 int threaded = 0, entry = 0, tag;
211 211 Lm_list *lml;
212 212 Lc_desc *lcp;
213 213
214 214 if ((lmp == NULL) || (funcs == NULL))
215 215 return;
216 216
217 217 /*
218 218 * Once the process is active, ensure we grab a lock.
219 219 */
220 220 if (rtld_flags & RT_FL_APPLIC)
221 221 entry = enter(0);
222 222
223 223 lml = LIST(lmp);
224 224 lcp = &lml->lm_lcs[0];
225 225
226 226 DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
227 227
228 228 for (tag = funcs->ci_tag; tag; tag = (++funcs)->ci_tag) {
229 229 char *gptr;
230 230 char *lptr = funcs->ci_un.ci_ptr;
231 231
232 232 DBG_CALL(Dbg_util_lcinterface(lmp, tag, lptr));
233 233
234 234 if (tag >= CI_MAX)
235 235 continue;
236 236
237 237 /*
238 238 * Maintain all interfaces on a per-link-map basis. Note, for
239 239 * most interfaces, only the first interface is used for any
240 240 * link-map list. This prevents accidents with developers who
241 241 * manage to load two different versions of libc.
242 242 */
243 243 if ((lcp[tag].lc_lmp) &&
244 244 (tag != CI_LCMESSAGES) && (tag != CI_VERSION)) {
245 245 DBG_CALL(Dbg_unused_lcinterface(lmp,
246 246 lcp[tag].lc_lmp, tag));
247 247 continue;
248 248 }
249 249
250 250 lcp[tag].lc_un.lc_ptr = lptr;
251 251 lcp[tag].lc_lmp = lmp;
252 252
253 253 gptr = glcs[tag].lc_un.lc_ptr;
254 254
255 255 /*
256 256 * Process any interfaces that must be maintained on a global
257 257 * basis.
258 258 */
259 259 switch (tag) {
260 260 case CI_ATEXIT:
261 261 break;
262 262
263 263 case CI_LCMESSAGES:
264 264 /*
265 265 * At startup, ld.so.1 can establish a locale from one
266 266 * of the locale family of environment variables (see
267 267 * ld_str_env() and readenv_user()). During process
268 268 * execution the locale can also be changed by the user.
269 269 * This interface is called from libc should the locale
270 270 * be modified. Presently, only one global locale is
271 271 * maintained for all link-map lists, and only objects
272 272 * on the primrary link-map may change this locale.
273 273 */
274 274 if ((lml->lm_flags & LML_FLG_BASELM) &&
275 275 ((gptr == NULL) || (strcmp(gptr, lptr) != 0))) {
276 276 /*
277 277 * If we've obtained a message locale (typically
278 278 * supplied via libc's setlocale()), then
279 279 * register the locale for use in dgettext() so
280 280 * as to reestablish the locale for ld.so.1's
281 281 * messages.
282 282 */
283 283 if (gptr) {
284 284 free((void *)gptr);
285 285 rtld_flags |= RT_FL_NEWLOCALE;
286 286 }
287 287 glcs[tag].lc_un.lc_ptr = strdup(lptr);
288 288
289 289 /*
290 290 * Clear any cached messages.
291 291 */
292 292 bzero(err_strs, sizeof (err_strs));
293 293 nosym_str = NULL;
294 294 }
295 295 break;
296 296
297 297 case CI_BIND_GUARD:
298 298 case CI_BIND_CLEAR:
299 299 case CI_THR_SELF:
300 300 case CI_CRITICAL:
301 301 /*
302 302 * If the global vector is unset, or this is the primary
303 303 * link-map, set the global vector.
304 304 */
305 305 if ((gptr == NULL) || (lml->lm_flags & LML_FLG_BASELM))
306 306 glcs[tag].lc_un.lc_ptr = lptr;
307 307
308 308 /* FALLTHROUGH */
309 309
310 310 case CI_TLS_MODADD:
311 311 case CI_TLS_MODREM:
312 312 case CI_TLS_STATMOD:
313 313 case CI_THRINIT:
314 314 threaded++;
315 315 break;
316 316
317 317 case CI_VERSION:
318 318 if ((rtld_flags2 & RT_FL2_RTLDSEEN) == 0) {
319 319 Aliste idx;
320 320 Lm_list *lml2;
321 321 int version;
322 322
323 323 rtld_flags2 |= RT_FL2_RTLDSEEN;
324 324
325 325 version = funcs->ci_un.ci_val;
326 326 #if defined(CI_V_FIVE)
327 327 if (version >= CI_V_FIVE) {
328 328 thr_flg_nolock = THR_FLG_NOLOCK;
329 329 thr_flg_reenter = THR_FLG_REENTER;
330 330 }
331 331 #endif
332 332 if (version < CI_V_FOUR)
333 333 break;
334 334
335 335 rtld_flags2 |= RT_FL2_UNIFPROC;
336 336
337 337 /*
338 338 * We might have seen an auditor which is not
339 339 * dependent on libc. Such an auditor's link
340 340 * map list has LML_FLG_HOLDLOCK set. This
341 341 * lock needs to be dropped. Refer to
342 342 * audit_setup() in audit.c.
343 343 */
344 344 if ((rtld_flags2 & RT_FL2_HASAUDIT) == 0)
345 345 break;
346 346
347 347 /*
348 348 * Yes, we did. Take care of them.
349 349 */
350 350 for (APLIST_TRAVERSE(dynlm_list, idx, lml2)) {
351 351 Rt_map *map = (Rt_map *)lml2->lm_head;
352 352
353 353 if (FLAGS(map) & FLG_RT_AUDIT) {
354 354 lml2->lm_flags &=
355 355 ~LML_FLG_HOLDLOCK;
356 356 }
357 357 }
358 358 }
359 359 break;
360 360
361 361 default:
362 362 break;
363 363 }
364 364 }
365 365
366 366 if (threaded) {
367 367 /*
368 368 * If a version of libc gives us only a subset of the TLS
369 369 * interfaces, it's confused and we discard the whole lot.
370 370 */
371 371 if ((lcp[CI_TLS_MODADD].lc_un.lc_func &&
372 372 lcp[CI_TLS_MODREM].lc_un.lc_func &&
373 373 lcp[CI_TLS_STATMOD].lc_un.lc_func) == NULL) {
374 374 lcp[CI_TLS_MODADD].lc_un.lc_func = NULL;
375 375 lcp[CI_TLS_MODREM].lc_un.lc_func = NULL;
376 376 lcp[CI_TLS_STATMOD].lc_un.lc_func = NULL;
377 377 }
378 378
379 379 /*
380 380 * Indicate that we're now thread capable.
381 381 */
382 382 if ((lml->lm_flags & LML_FLG_RTLDLM) == 0)
383 383 rtld_flags |= RT_FL_THREADS;
384 384 }
385 385
386 386 if (entry)
387 387 leave(lml, 0);
388 388 }
389 389
390 390 /*
391 391 * At this point we know we have a set of objects that have been fully analyzed
392 392 * and relocated. Prior to the next major step of running .init sections (ie.
393 393 * running user code), retrieve any RTLDINFO interfaces.
394 394 */
395 395 int
396 396 rt_get_extern(Lm_list *lml, Rt_map *lmp)
397 397 {
398 398 if (lml->lm_rti) {
399 399 Aliste idx;
400 400 Rti_desc *rti;
401 401
402 402 for (ALIST_TRAVERSE(lml->lm_rti, idx, rti))
403 403 get_lcinterface(rti->rti_lmp, rti->rti_info);
404 404
405 405 free(lml->lm_rti);
406 406 lml->lm_rti = 0;
407 407 }
408 408
409 409 /*
410 410 * Perform some sanity checks. If we have TLS requirements we better
411 411 * have the associated external interfaces.
412 412 */
413 413 if (lml->lm_tls &&
414 414 (lml->lm_lcs[CI_TLS_STATMOD].lc_un.lc_func == NULL)) {
415 415 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TLS_NOSUPPORT),
416 416 NAME(lmp));
417 417 return (0);
418 418 }
419 419 return (1);
420 420 }
421 421
422 422 /*
423 423 * Provide an interface for libc to communicate additional interface
424 424 * information.
425 425 */
426 426 void
427 427 _ld_libc(void *ptr)
428 428 {
429 429 get_lcinterface(_caller(caller(), CL_EXECDEF), (Lc_interface *)ptr);
430 430 }
431 431
432 432 static int bindmask = 0;
433 433
434 434 int
435 435 rt_bind_guard(int flags)
436 436 {
437 437 int (*fptr)(int);
438 438 int bindflag;
439 439
440 440 if ((fptr = glcs[CI_BIND_GUARD].lc_un.lc_func) != NULL) {
441 441 return ((*fptr)(flags));
442 442 } else {
443 443 bindflag = (flags & THR_FLG_RTLD);
444 444 if ((bindflag & bindmask) == 0) {
445 445 bindmask |= bindflag;
446 446 return (1);
447 447 }
448 448 return (0);
449 449 }
450 450 }
451 451
452 452 int
453 453 rt_bind_clear(int flags)
454 454 {
455 455 int (*fptr)(int);
456 456 int bindflag;
457 457
458 458 if ((fptr = glcs[CI_BIND_CLEAR].lc_un.lc_func) != NULL) {
459 459 return ((*fptr)(flags));
460 460 } else {
461 461 bindflag = (flags & THR_FLG_RTLD);
462 462 if (bindflag == 0)
463 463 return (bindmask);
464 464 else {
465 465 bindmask &= ~bindflag;
466 466 return (0);
467 467 }
468 468 }
469 469 }
470 470
471 471 /*
472 472 * Make sure threads have been initialized. This interface is called once for
473 473 * each link-map list.
474 474 */
475 475 void
476 476 rt_thr_init(Lm_list *lml)
477 477 {
478 478 void (*fptr)(void);
479 479
480 480 if ((fptr =
481 481 (void (*)())lml->lm_lcs[CI_THRINIT].lc_un.lc_func) != NULL) {
482 482 lml->lm_lcs[CI_THRINIT].lc_un.lc_func = NULL;
483 483
484 484 leave(lml, thr_flg_reenter);
485 485 (*fptr)();
486 486 (void) enter(thr_flg_reenter);
487 487
488 488 /*
489 489 * If this is an alternative link-map list, and this is the
490 490 * first call to initialize threads, don't let the destination
491 491 * libc be deleted. It is possible that an auditors complete
492 492 * initialization fails, but there is presently no main link-map
493 493 * list. As this libc has established the thread pointer, don't
494 494 * delete this libc, otherwise the initialization of libc on the
495 495 * main link-map can be compromised during its threads
496 496 * initialization.
497 497 */
498 498 if (((lml->lm_flags & LML_FLG_BASELM) == 0) &&
499 499 ((rtld_flags2 & RT_FL2_PLMSETUP) == 0))
500 500 MODE(lml->lm_lcs[CI_THRINIT].lc_lmp) |= RTLD_NODELETE;
501 501 }
502 502 }
503 503
504 504 thread_t
505 505 rt_thr_self()
506 506 {
507 507 thread_t (*fptr)(void);
508 508
509 509 if ((fptr = (thread_t (*)())glcs[CI_THR_SELF].lc_un.lc_func) != NULL)
510 510 return ((*fptr)());
511 511
512 512 return (1);
513 513 }
514 514
515 515 int
516 516 rt_mutex_lock(Rt_lock *mp)
517 517 {
518 518 return (_lwp_mutex_lock((lwp_mutex_t *)mp));
519 519 }
520 520
521 521 int
522 522 rt_mutex_unlock(Rt_lock *mp)
523 523 {
524 524 return (_lwp_mutex_unlock((lwp_mutex_t *)mp));
525 525 }
526 526
527 527 /*
528 528 * Test whether we're in a libc critical region. Certain function references,
529 529 * like the "mem*" family, might require binding. Although these functions can
530 530 * safely bind to auxiliary filtees, they should not be captured by auditors.
531 531 */
532 532 int
533 533 rt_critical()
534 534 {
535 535 int (*fptr)(void);
536 536
537 537 if ((fptr = glcs[CI_CRITICAL].lc_un.lc_func) != NULL)
538 538 return ((*fptr)());
539 539
540 540 return (0);
541 541 }
542 542
543 543 /*
544 544 * Mutex interfaces to resolve references from any objects extracted from
545 545 * libc_pic.a. Note, as ld.so.1 is essentially single threaded these can be
546 546 * noops.
547 547 */
548 548 #pragma weak lmutex_lock = mutex_lock
549 549 /* ARGSUSED */
550 550 int
551 551 mutex_lock(mutex_t *mp)
552 552 {
553 553 return (0);
554 554 }
555 555
556 556 #pragma weak lmutex_unlock = mutex_unlock
557 557 /* ARGSUSED */
558 558 int
559 559 mutex_unlock(mutex_t *mp)
560 560 {
561 561 return (0);
562 562 }
563 563
564 564 /* ARGSUSED */
565 565 int
566 566 mutex_init(mutex_t *mp, int type, void *arg)
567 567 {
568 568 return (0);
569 569 }
570 570
571 571 /* ARGSUSED */
572 572 int
573 573 mutex_destroy(mutex_t *mp)
574 574 {
575 575 return (0);
576 576 }
577 577
578 578 /*
579 579 * This is needed to satisfy sysconf() (case _SC_THREAD_STACK_MIN)
580 580 */
581 581 size_t
582 582 thr_min_stack()
583 583 {
584 584 return (sizeof (uintptr_t) * 1024);
585 585 }
586 586
587 587 /*
588 588 * Local str[n]casecmp() interfaces for the dynamic linker,
589 589 * to avoid problems when linking with libc_pic.a
590 590 */
591 591 int
592 592 strcasecmp(const char *s1, const char *s2)
593 593 {
594 594 extern int ascii_strcasecmp(const char *, const char *);
595 595
596 596 return (ascii_strcasecmp(s1, s2));
597 597 }
598 598
599 599 int
600 600 strncasecmp(const char *s1, const char *s2, size_t n)
601 601 {
602 602 extern int ascii_strncasecmp(const char *, const char *, size_t);
603 603
604 604 return (ascii_strncasecmp(s1, s2, n));
605 605 }
606 606
607 607 /*
608 608 * The following functions are cancellation points in libc.
609 609 * They are called from other functions in libc that we extract
610 610 * and use directly. We don't do cancellation while we are in
611 611 * the dynamic linker, so we redefine these to call the primitive,
612 612 * non-cancellation interfaces.
613 613 */
614 614 int
615 615 close(int fildes)
616 616 {
617 617 extern int __close(int);
618 618
619 619 return (__close(fildes));
620 620 }
621 621
622 622 int
623 623 fcntl(int fildes, int cmd, ...)
624 624 {
625 625 extern int __fcntl(int, int, ...);
626 626 intptr_t arg;
627 627 va_list ap;
628 628
629 629 va_start(ap, cmd);
630 630 arg = va_arg(ap, intptr_t);
631 631 va_end(ap);
632 632 return (__fcntl(fildes, cmd, arg));
633 633 }
634 634
635 635 int
636 636 open(const char *path, int oflag, ...)
637 637 {
638 638 extern int __open(const char *, int, mode_t);
639 639 mode_t mode;
640 640 va_list ap;
641 641
642 642 va_start(ap, oflag);
643 643 mode = va_arg(ap, mode_t);
644 644 va_end(ap);
645 645 return (__open(path, oflag, mode));
646 646 }
647 647
648 648 int
649 649 openat(int fd, const char *path, int oflag, ...)
650 650 {
651 651 extern int __openat(int, const char *, int, mode_t);
652 652 mode_t mode;
653 653 va_list ap;
654 654
655 655 va_start(ap, oflag);
656 656 mode = va_arg(ap, mode_t);
657 657 va_end(ap);
658 658 return (__openat(fd, path, oflag, mode));
659 659 }
660 660
661 661 ssize_t
662 662 read(int fd, void *buf, size_t size)
663 663 {
664 664 extern ssize_t __read(int, void *, size_t);
665 665 return (__read(fd, buf, size));
666 666 }
667 667
668 668 ssize_t
669 669 write(int fd, const void *buf, size_t size)
670 670 {
671 671 extern ssize_t __write(int, const void *, size_t);
672 672 return (__write(fd, buf, size));
673 673 }
674 674
675 675 /*
676 676 * ASCII versions of ctype character classification functions. This avoids
677 677 * pulling in the entire locale framework that is in libc.
678 678 */
679 679
680 680 int
681 681 isdigit(int c)
682 682 {
683 683 return ((c >= '0' && c <= '9') ? 1 : 0);
684 684 }
685 685
686 686 int
687 687 isupper(int c)
688 688 {
689 689 return ((c >= 'A' && c <= 'Z') ? 1 : 0);
690 690 }
691 691
692 692 int
693 693 islower(int c)
694 694 {
695 695 return ((c >= 'a' && c <= 'z') ? 1 : 0);
696 696 }
697 697
698 698 int
699 699 isspace(int c)
700 700 {
701 701 return (((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n') ||
702 702 (c == '\v') || (c == '\f')) ? 1 : 0);
703 703 }
704 704
705 705 int
706 706 isxdigit(int c)
707 707 {
708 708 return ((isdigit(c) || (c >= 'A' && c <= 'F') ||
709 709 (c >= 'a' && c <= 'f')) ? 1 : 0);
710 710 }
711 711
712 712 int
713 713 isalpha(int c)
|
↓ open down ↓ |
678 lines elided |
↑ open up ↑ |
714 714 {
715 715 return ((isupper(c) || islower(c)) ? 1 : 0);
716 716 }
717 717
718 718 int
719 719 isalnum(int c)
720 720 {
721 721 return ((isalpha(c) || isdigit(c)) ? 1 : 0);
722 722 }
723 723
724 +#if defined(__i386) || defined(__amd64)
724 725 /*
726 + * Instead of utilizing the comm page for clock_gettime, rtld uses the raw
727 + * syscall instead. Doing so decreases the surface of symbols needed from libc
728 + * for a modest performance cost.
729 + */
730 +extern int __clock_gettime_sys(clockid_t, struct timespec *);
731 +
732 +int
733 +__clock_gettime(clockid_t clock_id, struct timespec *tp)
734 +{
735 + return (__clock_gettime_sys(clock_id, tp));
736 +}
737 +#endif /* defined(__i386) || defined(__amd64) */
738 +
739 +/*
725 740 * In a similar vein to the is* functions above, we also have to define our own
726 741 * version of strerror, as it is implemented in terms of the locale aware
727 742 * strerror_l, and we'd rather not have the full set of libc symbols used here.
728 743 */
729 744 extern const char _sys_errs[];
730 745 extern const int _sys_index[];
731 746 extern int _sys_num_err;
732 747
733 748 char *
734 749 strerror(int errnum)
735 750 {
736 751 if (errnum < _sys_num_err && errnum >= 0) {
737 752 return (dgettext("SUNW_OST_OSLIB",
738 753 (char *)&_sys_errs[_sys_index[errnum]]));
739 754 }
740 755
741 756 errno = EINVAL;
742 757 return (dgettext("SUNW_OST_OSLIB", "Unknown error"));
743 758 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX