1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997,2008 Oracle. All rights reserved. 5 * 6 * $Id: os_yield.c,v 12.19 2008/01/08 20:58:43 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#define __INCLUDE_SELECT_H 1 12#include "db_int.h" 13 14#if defined(HAVE_SYSTEM_INCLUDE_FILES) && defined(HAVE_SCHED_YIELD) 15#include <sched.h> 16#endif 17 18static void __os_sleep __P((ENV *, u_long, u_long)); 19 20/* 21 * __os_yield -- 22 * Yield the processor, optionally pausing until running again. 23 * 24 * PUBLIC: void __os_yield __P((ENV *, u_long, u_long)); 25 */ 26void 27__os_yield(env, secs, usecs) 28 ENV *env; 29 u_long secs, usecs; /* Seconds and microseconds. */ 30{ 31 /* 32 * Don't require the values be normalized (some operating systems 33 * return an error if the usecs argument to select is too large). 34 */ 35 for (; usecs >= US_PER_SEC; usecs -= US_PER_SEC) 36 ++secs; 37 38 if (DB_GLOBAL(j_yield) != NULL) { 39 (void)DB_GLOBAL(j_yield)(secs, usecs); 40 return; 41 } 42 43 /* 44 * Yield the processor so other processes or threads can run. Use 45 * the local yield call if not pausing, otherwise call the select 46 * function. 47 */ 48 if (secs != 0 || usecs != 0) 49 __os_sleep(env, secs, usecs); 50 else { 51#if defined(HAVE_MUTEX_UI_THREADS) 52 thr_yield(); 53#elif defined(HAVE_PTHREAD_YIELD) && \ 54 (defined(HAVE_MUTEX_PTHREADS) || defined(HAVE_PTHREAD_API)) 55 pthread_yield(); 56#elif defined(HAVE_SCHED_YIELD) 57 (void)sched_yield(); 58#elif defined(HAVE_YIELD) 59 yield(); 60#else 61 __os_sleep(dbenv, 0, 0); 62#endif 63 } 64} 65 66/* 67 * __os_sleep -- 68 * Pause the thread of control. 69 */ 70static void 71__os_sleep(env, secs, usecs) 72 ENV *env; 73 u_long secs, usecs; /* Seconds and microseconds. */ 74{ 75 struct timeval t; 76 int ret; 77 78 /* 79 * Sheer raving paranoia -- don't select for 0 time, in case some 80 * implementation doesn't yield the processor in that case. 81 */ 82 t.tv_sec = (long)secs; 83 t.tv_usec = (long)usecs + 1; 84 85 /* 86 * We don't catch interrupts and restart the system call here, unlike 87 * other Berkeley DB system calls. This may be a user attempting to 88 * interrupt a sleeping DB utility (for example, db_checkpoint), and 89 * we want the utility to see the signal and quit. This assumes it's 90 * always OK for DB to sleep for less time than originally scheduled. 91 */ 92 if (select(0, NULL, NULL, NULL, &t) == -1) { 93 ret = __os_get_syserr(); 94 if (__os_posix_err(ret) != EINTR) 95 __db_syserr(env, ret, "select"); 96 } 97} 98