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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "umem_base.h" 30 #include "vmem_base.h" 31 32 #include <signal.h> 33 34 /* 35 * we use the _ version, since we don't want to be cancelled. 36 */ 37 extern int _cond_timedwait(cond_t *cv, mutex_t *mutex, const timespec_t *delay); 38 39 /*ARGSUSED*/ 40 static void * 41 umem_update_thread(void *arg) 42 { 43 struct timeval now; 44 int in_update = 0; 45 46 (void) mutex_lock(&umem_update_lock); 47 48 ASSERT(umem_update_thr == thr_self()); 49 ASSERT(umem_st_update_thr == 0); 50 51 for (;;) { 52 umem_process_updates(); 53 54 if (in_update) { 55 in_update = 0; 56 /* 57 * we wait until now to set the next update time 58 * so that the updates are self-throttling 59 */ 60 (void) gettimeofday(&umem_update_next, NULL); 61 umem_update_next.tv_sec += umem_reap_interval; 62 } 63 64 switch (umem_reaping) { 65 case UMEM_REAP_DONE: 66 case UMEM_REAP_ADDING: 67 break; 68 69 case UMEM_REAP_ACTIVE: 70 umem_reap_next = gethrtime() + 71 (hrtime_t)umem_reap_interval * NANOSEC; 72 umem_reaping = UMEM_REAP_DONE; 73 break; 74 75 default: 76 ASSERT(umem_reaping == UMEM_REAP_DONE || 77 umem_reaping == UMEM_REAP_ADDING || 78 umem_reaping == UMEM_REAP_ACTIVE); 79 break; 80 } 81 82 (void) gettimeofday(&now, NULL); 83 if (now.tv_sec > umem_update_next.tv_sec || 84 (now.tv_sec == umem_update_next.tv_sec && 85 now.tv_usec >= umem_update_next.tv_usec)) { 86 /* 87 * Time to run an update 88 */ 89 (void) mutex_unlock(&umem_update_lock); 90 91 vmem_update(NULL); 92 /* 93 * umem_cache_update can use umem_add_update to 94 * request further work. The update is not complete 95 * until all such work is finished. 96 */ 97 umem_cache_applyall(umem_cache_update); 98 99 (void) mutex_lock(&umem_update_lock); 100 in_update = 1; 101 continue; /* start processing immediately */ 102 } 103 104 /* 105 * if there is no work to do, we wait until it is time for 106 * next update, or someone wakes us. 107 */ 108 if (umem_null_cache.cache_unext == &umem_null_cache) { 109 timespec_t abs_time; 110 abs_time.tv_sec = umem_update_next.tv_sec; 111 abs_time.tv_nsec = umem_update_next.tv_usec * 1000; 112 113 (void) _cond_timedwait(&umem_update_cv, 114 &umem_update_lock, &abs_time); 115 } 116 } 117 /* LINTED no return statement */ 118 } 119 120 int 121 umem_create_update_thread(void) 122 { 123 sigset_t sigmask, oldmask; 124 125 ASSERT(MUTEX_HELD(&umem_update_lock)); 126 ASSERT(umem_update_thr == 0); 127 128 /* 129 * The update thread handles no signals 130 */ 131 (void) sigfillset(&sigmask); 132 (void) thr_sigsetmask(SIG_BLOCK, &sigmask, &oldmask); 133 if (thr_create(NULL, NULL, umem_update_thread, NULL, 134 THR_BOUND | THR_DAEMON | THR_DETACHED, &umem_update_thr) == 0) { 135 (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 136 return (1); 137 } 138 umem_update_thr = 0; 139 (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 140 return (0); 141 } 142