17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5d02b2eccSbarts * Common Development and Distribution License (the "License"). 6d02b2eccSbarts * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21a574db85Sraf 227c478bd9Sstevel@tonic-gate /* 23a574db85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include "umem_base.h" 287c478bd9Sstevel@tonic-gate #include "vmem_base.h" 297c478bd9Sstevel@tonic-gate 30*9e293969SRichard Lowe #include <sys/ccompile.h> 31*9e293969SRichard Lowe 327c478bd9Sstevel@tonic-gate #include <signal.h> 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 35*9e293969SRichard Lowe static void * __NORETURN 367c478bd9Sstevel@tonic-gate umem_update_thread(void *arg) 377c478bd9Sstevel@tonic-gate { 387c478bd9Sstevel@tonic-gate struct timeval now; 397c478bd9Sstevel@tonic-gate int in_update = 0; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate (void) mutex_lock(&umem_update_lock); 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate ASSERT(umem_update_thr == thr_self()); 447c478bd9Sstevel@tonic-gate ASSERT(umem_st_update_thr == 0); 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate for (;;) { 477c478bd9Sstevel@tonic-gate umem_process_updates(); 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate if (in_update) { 507c478bd9Sstevel@tonic-gate in_update = 0; 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * we wait until now to set the next update time 537c478bd9Sstevel@tonic-gate * so that the updates are self-throttling 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate (void) gettimeofday(&umem_update_next, NULL); 567c478bd9Sstevel@tonic-gate umem_update_next.tv_sec += umem_reap_interval; 577c478bd9Sstevel@tonic-gate } 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate switch (umem_reaping) { 607c478bd9Sstevel@tonic-gate case UMEM_REAP_DONE: 617c478bd9Sstevel@tonic-gate case UMEM_REAP_ADDING: 627c478bd9Sstevel@tonic-gate break; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate case UMEM_REAP_ACTIVE: 657c478bd9Sstevel@tonic-gate umem_reap_next = gethrtime() + 667c478bd9Sstevel@tonic-gate (hrtime_t)umem_reap_interval * NANOSEC; 677c478bd9Sstevel@tonic-gate umem_reaping = UMEM_REAP_DONE; 687c478bd9Sstevel@tonic-gate break; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate default: 717c478bd9Sstevel@tonic-gate ASSERT(umem_reaping == UMEM_REAP_DONE || 727c478bd9Sstevel@tonic-gate umem_reaping == UMEM_REAP_ADDING || 737c478bd9Sstevel@tonic-gate umem_reaping == UMEM_REAP_ACTIVE); 747c478bd9Sstevel@tonic-gate break; 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, NULL); 787c478bd9Sstevel@tonic-gate if (now.tv_sec > umem_update_next.tv_sec || 797c478bd9Sstevel@tonic-gate (now.tv_sec == umem_update_next.tv_sec && 807c478bd9Sstevel@tonic-gate now.tv_usec >= umem_update_next.tv_usec)) { 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * Time to run an update 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate (void) mutex_unlock(&umem_update_lock); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate vmem_update(NULL); 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * umem_cache_update can use umem_add_update to 897c478bd9Sstevel@tonic-gate * request further work. The update is not complete 907c478bd9Sstevel@tonic-gate * until all such work is finished. 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate umem_cache_applyall(umem_cache_update); 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate (void) mutex_lock(&umem_update_lock); 957c478bd9Sstevel@tonic-gate in_update = 1; 967c478bd9Sstevel@tonic-gate continue; /* start processing immediately */ 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * if there is no work to do, we wait until it is time for 1017c478bd9Sstevel@tonic-gate * next update, or someone wakes us. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate if (umem_null_cache.cache_unext == &umem_null_cache) { 104a574db85Sraf int cancel_state; 1057c478bd9Sstevel@tonic-gate timespec_t abs_time; 1067c478bd9Sstevel@tonic-gate abs_time.tv_sec = umem_update_next.tv_sec; 1077c478bd9Sstevel@tonic-gate abs_time.tv_nsec = umem_update_next.tv_usec * 1000; 1087c478bd9Sstevel@tonic-gate 109a574db85Sraf (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 110a574db85Sraf &cancel_state); 111a574db85Sraf (void) cond_timedwait(&umem_update_cv, 1127c478bd9Sstevel@tonic-gate &umem_update_lock, &abs_time); 113a574db85Sraf (void) pthread_setcancelstate(cancel_state, NULL); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate } 1164e4fe0d7Sbarts /* LINTED no return statement */ 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate int 1207c478bd9Sstevel@tonic-gate umem_create_update_thread(void) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate sigset_t sigmask, oldmask; 123d02b2eccSbarts thread_t newthread; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&umem_update_lock)); 1267c478bd9Sstevel@tonic-gate ASSERT(umem_update_thr == 0); 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * The update thread handles no signals 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate (void) sigfillset(&sigmask); 1327c478bd9Sstevel@tonic-gate (void) thr_sigsetmask(SIG_BLOCK, &sigmask, &oldmask); 133d02b2eccSbarts 134d02b2eccSbarts /* 135d02b2eccSbarts * drop the umem_update_lock; we cannot hold locks acquired in 136d02b2eccSbarts * pre-fork handler while calling thr_create or thr_continue(). 137d02b2eccSbarts */ 138d02b2eccSbarts 139d02b2eccSbarts (void) mutex_unlock(&umem_update_lock); 140d02b2eccSbarts 1417c478bd9Sstevel@tonic-gate if (thr_create(NULL, NULL, umem_update_thread, NULL, 142d02b2eccSbarts THR_BOUND | THR_DAEMON | THR_DETACHED | THR_SUSPENDED, 143d02b2eccSbarts &newthread) == 0) { 1447c478bd9Sstevel@tonic-gate (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 145d02b2eccSbarts 146d02b2eccSbarts (void) mutex_lock(&umem_update_lock); 147d02b2eccSbarts /* 148d02b2eccSbarts * due to the locking in umem_reap(), only one thread can 149d02b2eccSbarts * ever call umem_create_update_thread() at a time. This 150d02b2eccSbarts * must be the case for this code to work. 151d02b2eccSbarts */ 152d02b2eccSbarts 153d02b2eccSbarts ASSERT(umem_update_thr == 0); 154d02b2eccSbarts umem_update_thr = newthread; 155d02b2eccSbarts (void) mutex_unlock(&umem_update_lock); 156d02b2eccSbarts (void) thr_continue(newthread); 157d02b2eccSbarts (void) mutex_lock(&umem_update_lock); 158d02b2eccSbarts 1597c478bd9Sstevel@tonic-gate return (1); 160d02b2eccSbarts } else { /* thr_create failed */ 1617c478bd9Sstevel@tonic-gate (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 162d02b2eccSbarts (void) mutex_lock(&umem_update_lock); 163d02b2eccSbarts } 1647c478bd9Sstevel@tonic-gate return (0); 1657c478bd9Sstevel@tonic-gate } 166