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 5f635d46aSqiao * Common Development and Distribution License (the "License"). 6f635d46aSqiao * 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 */ 217c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 227c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 26f635d46aSqiao * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 27f635d46aSqiao * Use is subject to license terms. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #ifndef _SYS_CALLO_H 317c478bd9Sstevel@tonic-gate #define _SYS_CALLO_H 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 347c478bd9Sstevel@tonic-gate #include <sys/taskq.h> 35*87a18d3fSMadhavan Venkataraman #include <sys/lgrp.h> 36*87a18d3fSMadhavan Venkataraman #include <sys/processor.h> 37*87a18d3fSMadhavan Venkataraman #include <sys/cyclic.h> 38*87a18d3fSMadhavan Venkataraman #include <sys/kstat.h> 39*87a18d3fSMadhavan Venkataraman #include <sys/systm.h> 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #ifdef __cplusplus 427c478bd9Sstevel@tonic-gate extern "C" { 437c478bd9Sstevel@tonic-gate #endif 447c478bd9Sstevel@tonic-gate 45*87a18d3fSMadhavan Venkataraman #ifdef _KERNEL 46*87a18d3fSMadhavan Venkataraman 47*87a18d3fSMadhavan Venkataraman typedef struct callout_list callout_list_t; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* 507c478bd9Sstevel@tonic-gate * The callout mechanism provides general-purpose event scheduling: 517c478bd9Sstevel@tonic-gate * an arbitrary function is called in a specified amount of time. 52*87a18d3fSMadhavan Venkataraman * The expiration time for a callout is kept in its callout list 53*87a18d3fSMadhavan Venkataraman * structure. 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate typedef struct callout { 567c478bd9Sstevel@tonic-gate struct callout *c_idnext; /* next in ID hash, or on freelist */ 577c478bd9Sstevel@tonic-gate struct callout *c_idprev; /* prev in ID hash */ 58*87a18d3fSMadhavan Venkataraman struct callout *c_clnext; /* next in callout list */ 59*87a18d3fSMadhavan Venkataraman struct callout *c_clprev; /* prev in callout list */ 607c478bd9Sstevel@tonic-gate callout_id_t c_xid; /* extended callout ID; see below */ 61*87a18d3fSMadhavan Venkataraman callout_list_t *c_list; /* callout list */ 627c478bd9Sstevel@tonic-gate void (*c_func)(void *); /* function to call */ 637c478bd9Sstevel@tonic-gate void *c_arg; /* argument to function */ 647c478bd9Sstevel@tonic-gate } callout_t; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 67*87a18d3fSMadhavan Venkataraman * The callout ID (callout_id_t) uniquely identifies a callout. The callout 68*87a18d3fSMadhavan Venkataraman * ID is always 64 bits internally. The lower 32 bits contain an ID value. 69*87a18d3fSMadhavan Venkataraman * The upper 32 bits contain a generation number and flags. When the ID value 70*87a18d3fSMadhavan Venkataraman * wraps the generation number is incremented during ID generation. This 71*87a18d3fSMadhavan Venkataraman * protects callers from ID collisions that can happen as a result of the wrap. 727c478bd9Sstevel@tonic-gate * 73*87a18d3fSMadhavan Venkataraman * The kernel internal interface, timeout_generic(), always returns a 74*87a18d3fSMadhavan Venkataraman * callout_id_t. But the legacy interfaces, timeout() and realtime_timeout() 75*87a18d3fSMadhavan Venkataraman * return a timeout_id_t. On a 64-bit system, timeout_id_t is also 64 bits. 76*87a18d3fSMadhavan Venkataraman * So, the full 64-bit ID (sans the flags) can be returned. However, on 32-bit 77*87a18d3fSMadhavan Venkataraman * systems, timeout_id_t is 32 bits. So, only the lower 32 bits can be 78*87a18d3fSMadhavan Venkataraman * returned. In such cases, a default generation number of 0 is assigned to 79*87a18d3fSMadhavan Venkataraman * the legacy IDs. 80*87a18d3fSMadhavan Venkataraman * 81*87a18d3fSMadhavan Venkataraman * The lower 32-bit ID space is partitioned into two spaces - one for 32-bit 82*87a18d3fSMadhavan Venkataraman * IDs and the other for 64-bit IDs. The 32-bit ID space is further divided 83*87a18d3fSMadhavan Venkataraman * into two spaces - one for short-term callouts and one for long-term. 84*87a18d3fSMadhavan Venkataraman * 85*87a18d3fSMadhavan Venkataraman * Here is the bit layout for the callout ID: 86*87a18d3fSMadhavan Venkataraman * 87*87a18d3fSMadhavan Venkataraman * 63 62 61 ... 32 31 30 29 .. X+1 X ... 1 0 88*87a18d3fSMadhavan Venkataraman * ----------------------------------------------------------------------- 89*87a18d3fSMadhavan Venkataraman * | Exec | Hres | Generation | Long | Counter | ID bits | Table | Type | 90*87a18d3fSMadhavan Venkataraman * | | time | number | term | High | | number | | 91*87a18d3fSMadhavan Venkataraman * ----------------------------------------------------------------------- 92*87a18d3fSMadhavan Venkataraman * 93*87a18d3fSMadhavan Venkataraman * Exec(uting): 94*87a18d3fSMadhavan Venkataraman * This is the executing bit which is only set in the extended callout 95*87a18d3fSMadhavan Venkataraman * ID. This bit indicates that the callout handler is currently being 96*87a18d3fSMadhavan Venkataraman * executed. 97*87a18d3fSMadhavan Venkataraman * 98*87a18d3fSMadhavan Venkataraman * Hrestime: 99*87a18d3fSMadhavan Venkataraman * Kernel features like condition variables use hrestime (system date) in 100*87a18d3fSMadhavan Venkataraman * conjunction with callouts. Under normal circumstances, these callouts 101*87a18d3fSMadhavan Venkataraman * are handled in the usual manner. They go off at specified times. But 102*87a18d3fSMadhavan Venkataraman * when the system time is changed abruptly (e.g., via stime()), these 103*87a18d3fSMadhavan Venkataraman * callouts are required to be processed immediately so that they can 104*87a18d3fSMadhavan Venkataraman * wakeup their threads immediately. The Hrestime bit is used to mark 105*87a18d3fSMadhavan Venkataraman * such callouts. When the system time is changed, the callout subsystem 106*87a18d3fSMadhavan Venkataraman * is called to process all callouts with this bit set. 107*87a18d3fSMadhavan Venkataraman * 108*87a18d3fSMadhavan Venkataraman * Generation number: 109*87a18d3fSMadhavan Venkataraman * This is the generation part of the ID. 110*87a18d3fSMadhavan Venkataraman * 111*87a18d3fSMadhavan Venkataraman * Long term: 112*87a18d3fSMadhavan Venkataraman * This bit indicates whether this is a short-term or a long-term callout. 113*87a18d3fSMadhavan Venkataraman * The long-term bit exists to address the problem of callout ID collision 114*87a18d3fSMadhavan Venkataraman * on 32-bit systems. This is an issue because the system typically 115*87a18d3fSMadhavan Venkataraman * generates a large number of timeout() requests, which means that callout 116*87a18d3fSMadhavan Venkataraman * IDs eventually get recycled. Most timeouts are very short-lived, so that 117*87a18d3fSMadhavan Venkataraman * ID recycling isn't a problem; but there are a handful of timeouts which 118*87a18d3fSMadhavan Venkataraman * are sufficiently long-lived to see their own IDs reused. We use the 119*87a18d3fSMadhavan Venkataraman * long-term bit to partition the ID namespace into pieces; the short-term 120*87a18d3fSMadhavan Venkataraman * space gets all the heavy traffic and can wrap frequently (i.e., on the 121*87a18d3fSMadhavan Venkataraman * order of a day) with no ill effects; the long-term space gets very little 122*87a18d3fSMadhavan Venkataraman * traffic and thus never wraps. That said, we need to future proof callouts 123*87a18d3fSMadhavan Venkataraman * in case 32-bit systems grow in size and are able to consume callout IDs 124*87a18d3fSMadhavan Venkataraman * at faster rates. So, we should make all the kernel clients that use 125*87a18d3fSMadhavan Venkataraman * callouts to use the internal interface so that they can use IDs outside 126*87a18d3fSMadhavan Venkataraman * of the legacy space with a proper generation number. 127*87a18d3fSMadhavan Venkataraman * 128*87a18d3fSMadhavan Venkataraman * Counter High + ID counter bits: 129*87a18d3fSMadhavan Venkataraman * These bits represent the actual ID bits in the callout ID. 1307c478bd9Sstevel@tonic-gate * The highest bit of the running counter is always set; this ensures that 1317c478bd9Sstevel@tonic-gate * the callout ID is always non-zero, thus eliminating the need for an 1327c478bd9Sstevel@tonic-gate * explicit wrap-around test during ID generation. 1337c478bd9Sstevel@tonic-gate * 134*87a18d3fSMadhavan Venkataraman * Table number: 135*87a18d3fSMadhavan Venkataraman * These bits carry the table number for the callout table where the callout 136*87a18d3fSMadhavan Venkataraman * is queued. Each CPU has its own callout table. So, the callout tables are 137*87a18d3fSMadhavan Venkataraman * numbered from 0 - (max_ncpus - 1). Because max_ncpus is different on 138*87a18d3fSMadhavan Venkataraman * different systems, the actual number of table number bits will vary 139*87a18d3fSMadhavan Venkataraman * accordingly. And so will the ID counter bits. 140*87a18d3fSMadhavan Venkataraman * 141*87a18d3fSMadhavan Venkataraman * Type: 142*87a18d3fSMadhavan Venkataraman * This bit represents the callout (table) type. Each CPU has one realtime 143*87a18d3fSMadhavan Venkataraman * and one normal callout table. 1447c478bd9Sstevel@tonic-gate */ 145*87a18d3fSMadhavan Venkataraman #define CALLOUT_EXECUTING 0x8000000000000000ULL 146*87a18d3fSMadhavan Venkataraman #define CALLOUT_HRESTIME 0x4000000000000000ULL 147*87a18d3fSMadhavan Venkataraman #define CALLOUT_ID_MASK ~(CALLOUT_EXECUTING | CALLOUT_HRESTIME) 148*87a18d3fSMadhavan Venkataraman #define CALLOUT_GENERATION_LOW 0x100000000ULL 149*87a18d3fSMadhavan Venkataraman #define CALLOUT_LONGTERM 0x80000000 150*87a18d3fSMadhavan Venkataraman #define CALLOUT_COUNTER_HIGH 0x40000000 1517c478bd9Sstevel@tonic-gate #define CALLOUT_TYPE_BITS 1 1527c478bd9Sstevel@tonic-gate #define CALLOUT_NTYPES (1 << CALLOUT_TYPE_BITS) 153*87a18d3fSMadhavan Venkataraman #define CALLOUT_TYPE_MASK (CALLOUT_NTYPES - 1) 154*87a18d3fSMadhavan Venkataraman #define CALLOUT_COUNTER_SHIFT callout_table_bits 155*87a18d3fSMadhavan Venkataraman #define CALLOUT_TABLE(t, f) (((f) << CALLOUT_TYPE_BITS) | (t)) 156*87a18d3fSMadhavan Venkataraman #define CALLOUT_TABLE_NUM(ct) ((ct) - callout_table) 157*87a18d3fSMadhavan Venkataraman #define CALLOUT_TABLE_TYPE(ct) (CALLOUT_TABLE_NUM(ct) & CALLOUT_TYPE_MASK) 158*87a18d3fSMadhavan Venkataraman #define CALLOUT_TABLE_SEQID(ct) (CALLOUT_TABLE_NUM(ct) >> CALLOUT_TYPE_BITS) 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate /* 1617c478bd9Sstevel@tonic-gate * We assume that during any period of CALLOUT_LONGTERM_TICKS ticks, at most 162*87a18d3fSMadhavan Venkataraman * (CALLOUT_COUNTER_HIGH / callout_counter_low) callouts will be generated. 1637c478bd9Sstevel@tonic-gate */ 164*87a18d3fSMadhavan Venkataraman #define CALLOUT_LONGTERM_TICKS 0x4000UL 165*87a18d3fSMadhavan Venkataraman #define CALLOUT_BUCKET_SHIFT 9 166*87a18d3fSMadhavan Venkataraman #define CALLOUT_BUCKETS (1 << CALLOUT_BUCKET_SHIFT) 1677c478bd9Sstevel@tonic-gate #define CALLOUT_BUCKET_MASK (CALLOUT_BUCKETS - 1) 1687c478bd9Sstevel@tonic-gate #define CALLOUT_HASH(x) ((x) & CALLOUT_BUCKET_MASK) 1697c478bd9Sstevel@tonic-gate #define CALLOUT_IDHASH(x) CALLOUT_HASH((x) >> CALLOUT_COUNTER_SHIFT) 170*87a18d3fSMadhavan Venkataraman /* 171*87a18d3fSMadhavan Venkataraman * The multiply by 0 and 1 below are cosmetic. Just to align things better 172*87a18d3fSMadhavan Venkataraman * and make it more readable. The multiplications will be done at compile 173*87a18d3fSMadhavan Venkataraman * time. 174*87a18d3fSMadhavan Venkataraman */ 175*87a18d3fSMadhavan Venkataraman #define CALLOUT_CLHASH(x) \ 176*87a18d3fSMadhavan Venkataraman CALLOUT_HASH( \ 177*87a18d3fSMadhavan Venkataraman ((x)>>(CALLOUT_BUCKET_SHIFT*0)) ^ \ 178*87a18d3fSMadhavan Venkataraman ((x)>>(CALLOUT_BUCKET_SHIFT*1)) ^ \ 179*87a18d3fSMadhavan Venkataraman ((x)>>(CALLOUT_BUCKET_SHIFT*2)) ^ \ 180*87a18d3fSMadhavan Venkataraman ((x)>>(CALLOUT_BUCKET_SHIFT*3))) 181*87a18d3fSMadhavan Venkataraman 182*87a18d3fSMadhavan Venkataraman #define CALLOUT_ID_TO_TABLE(id) ((id) & callout_table_mask) 183*87a18d3fSMadhavan Venkataraman 184*87a18d3fSMadhavan Venkataraman #define CALLOUT_SHORT_ID(table) \ 185*87a18d3fSMadhavan Venkataraman ((callout_id_t)(table) | CALLOUT_COUNTER_HIGH) 186*87a18d3fSMadhavan Venkataraman #define CALLOUT_LONG_ID(table) \ 187*87a18d3fSMadhavan Venkataraman (CALLOUT_SHORT_ID(table) | CALLOUT_LONGTERM) 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate #define CALLOUT_THREADS 2 /* keep it simple for now */ 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate #define CALLOUT_REALTIME 0 /* realtime callout type */ 1927c478bd9Sstevel@tonic-gate #define CALLOUT_NORMAL 1 /* normal callout type */ 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 195*87a18d3fSMadhavan Venkataraman * callout_t's are cache-aligned structures allocated from kmem caches. One kmem 196*87a18d3fSMadhavan Venkataraman * cache is created per lgrp and is shared by all CPUs in that lgrp. Benefits: 197*87a18d3fSMadhavan Venkataraman * - cache pages are mapped only in the TLBs of the CPUs of the lgrp 198*87a18d3fSMadhavan Venkataraman * - data in cache pages is present only in those CPU caches 199*87a18d3fSMadhavan Venkataraman * - memory access performance improves with locality-awareness in kmem 200*87a18d3fSMadhavan Venkataraman * 201*87a18d3fSMadhavan Venkataraman * The following structure is used to manage per-lgroup kmem caches. 202*87a18d3fSMadhavan Venkataraman * 203*87a18d3fSMadhavan Venkataraman * NOTE: Free callout_t's go to a callout table's freelist. CPUs map to callout 204*87a18d3fSMadhavan Venkataraman * tables via their sequence IDs, not CPU IDs. DR operations can cause a 205*87a18d3fSMadhavan Venkataraman * free list to have callouts from multiple lgrp caches. This takes away some 206*87a18d3fSMadhavan Venkataraman * performance, but is no worse than if we did not use lgrp caches at all. 207*87a18d3fSMadhavan Venkataraman */ 208*87a18d3fSMadhavan Venkataraman typedef struct callout_cache { 209*87a18d3fSMadhavan Venkataraman struct callout_cache *cc_next; /* link in the global list */ 210*87a18d3fSMadhavan Venkataraman lgrp_handle_t cc_hand; /* lgroup handle */ 211*87a18d3fSMadhavan Venkataraman kmem_cache_t *cc_cache; /* kmem cache pointer */ 212*87a18d3fSMadhavan Venkataraman kmem_cache_t *cc_lcache; /* kmem cache pointer */ 213*87a18d3fSMadhavan Venkataraman } callout_cache_t; 214*87a18d3fSMadhavan Venkataraman 215*87a18d3fSMadhavan Venkataraman /* 216*87a18d3fSMadhavan Venkataraman * The callout hash structure is used for queueing both callouts and 217*87a18d3fSMadhavan Venkataraman * callout lists. That is why the fields are declared as void *. 218*87a18d3fSMadhavan Venkataraman */ 219*87a18d3fSMadhavan Venkataraman typedef struct callout_hash { 220*87a18d3fSMadhavan Venkataraman void *ch_head; 221*87a18d3fSMadhavan Venkataraman void *ch_tail; 222*87a18d3fSMadhavan Venkataraman } callout_hash_t; 223*87a18d3fSMadhavan Venkataraman 224*87a18d3fSMadhavan Venkataraman struct callout_list { 225*87a18d3fSMadhavan Venkataraman callout_list_t *cl_next; /* next in clhash */ 226*87a18d3fSMadhavan Venkataraman callout_list_t *cl_prev; /* prev in clhash */ 227*87a18d3fSMadhavan Venkataraman hrtime_t cl_expiration; /* expiration for callouts in list */ 228*87a18d3fSMadhavan Venkataraman callout_hash_t cl_callouts; /* list of callouts */ 229*87a18d3fSMadhavan Venkataraman kcondvar_t cl_done; /* signal callout completion */ 230*87a18d3fSMadhavan Venkataraman ushort_t cl_waiting; /* count of waiting untimeouts */ 231*87a18d3fSMadhavan Venkataraman kthread_id_t cl_executor; /* thread executing callout */ 232*87a18d3fSMadhavan Venkataraman ulong_t cl_pad; /* cache alignment */ 233*87a18d3fSMadhavan Venkataraman }; 234*87a18d3fSMadhavan Venkataraman 235*87a18d3fSMadhavan Venkataraman /* 236*87a18d3fSMadhavan Venkataraman * Per-callout table kstats. 237*87a18d3fSMadhavan Venkataraman * 238*87a18d3fSMadhavan Venkataraman * CALLOUT_TIMEOUTS 239*87a18d3fSMadhavan Venkataraman * Callouts created since boot. 240*87a18d3fSMadhavan Venkataraman * CALLOUT_TIMEOUTS_PENDING 241*87a18d3fSMadhavan Venkataraman * Number of outstanding callouts. 242*87a18d3fSMadhavan Venkataraman * CALLOUT_UNTIMEOUTS_UNEXPIRED 243*87a18d3fSMadhavan Venkataraman * Number of cancelled callouts that have not expired. 244*87a18d3fSMadhavan Venkataraman * CALLOUT_UNTIMEOUTS_EXECUTING 245*87a18d3fSMadhavan Venkataraman * Number of cancelled callouts that were executing at the time of 246*87a18d3fSMadhavan Venkataraman * cancellation. 247*87a18d3fSMadhavan Venkataraman * CALLOUT_UNTIMEOUTS_EXPIRED 248*87a18d3fSMadhavan Venkataraman * Number of cancelled callouts that had already expired at the time 249*87a18d3fSMadhavan Venkataraman * of cancellations. 250*87a18d3fSMadhavan Venkataraman * CALLOUT_EXPIRATIONS 251*87a18d3fSMadhavan Venkataraman * Number of callouts that expired. 252*87a18d3fSMadhavan Venkataraman * CALLOUT_ALLOCATIONS 253*87a18d3fSMadhavan Venkataraman * Number of callout structures allocated. 254*87a18d3fSMadhavan Venkataraman */ 255*87a18d3fSMadhavan Venkataraman typedef enum callout_stat_type { 256*87a18d3fSMadhavan Venkataraman CALLOUT_TIMEOUTS, 257*87a18d3fSMadhavan Venkataraman CALLOUT_TIMEOUTS_PENDING, 258*87a18d3fSMadhavan Venkataraman CALLOUT_UNTIMEOUTS_UNEXPIRED, 259*87a18d3fSMadhavan Venkataraman CALLOUT_UNTIMEOUTS_EXECUTING, 260*87a18d3fSMadhavan Venkataraman CALLOUT_UNTIMEOUTS_EXPIRED, 261*87a18d3fSMadhavan Venkataraman CALLOUT_EXPIRATIONS, 262*87a18d3fSMadhavan Venkataraman CALLOUT_ALLOCATIONS, 263*87a18d3fSMadhavan Venkataraman CALLOUT_NUM_STATS 264*87a18d3fSMadhavan Venkataraman } callout_stat_type_t; 265*87a18d3fSMadhavan Venkataraman 266*87a18d3fSMadhavan Venkataraman /* 267*87a18d3fSMadhavan Venkataraman * Callout flags: 268*87a18d3fSMadhavan Venkataraman * 269*87a18d3fSMadhavan Venkataraman * CALLOUT_FLAG_ROUNDUP 270*87a18d3fSMadhavan Venkataraman * Roundup the expiration time to the nearest resolution boundary. 271*87a18d3fSMadhavan Venkataraman * If this flag is not specified, the expiration time is rounded down. 272*87a18d3fSMadhavan Venkataraman * CALLOUT_FLAG_ABSOLUTE 273*87a18d3fSMadhavan Venkataraman * Normally, the expiration passed to the timeout API functions is an 274*87a18d3fSMadhavan Venkataraman * expiration interval. If this flag is specified, then it is 275*87a18d3fSMadhavan Venkataraman * interpreted as the expiration time itself. 276*87a18d3fSMadhavan Venkataraman * CALLOUT_FLAG_HRESTIME 277*87a18d3fSMadhavan Venkataraman * Normally, callouts are not affected by changes to system time 278*87a18d3fSMadhavan Venkataraman * (hrestime). This flag is used to create a callout that is affected 279*87a18d3fSMadhavan Venkataraman * by system time. If system time changes, these timers must expire 280*87a18d3fSMadhavan Venkataraman * at once. These are used by condition variables and LWP timers that 281*87a18d3fSMadhavan Venkataraman * need this behavior. 282*87a18d3fSMadhavan Venkataraman * CALLOUT_FLAG_32BIT 283*87a18d3fSMadhavan Venkataraman * Legacy interfaces timeout() and realtime_timeout() pass this flag 284*87a18d3fSMadhavan Venkataraman * to timeout_generic() to indicate that a 32-bit ID should be allocated. 285*87a18d3fSMadhavan Venkataraman */ 286*87a18d3fSMadhavan Venkataraman #define CALLOUT_FLAG_ROUNDUP 0x1 287*87a18d3fSMadhavan Venkataraman #define CALLOUT_FLAG_ABSOLUTE 0x2 288*87a18d3fSMadhavan Venkataraman #define CALLOUT_FLAG_HRESTIME 0x4 289*87a18d3fSMadhavan Venkataraman #define CALLOUT_FLAG_32BIT 0x8 290*87a18d3fSMadhavan Venkataraman 291*87a18d3fSMadhavan Venkataraman /* 292*87a18d3fSMadhavan Venkataraman * On 32-bit systems, the legacy interfaces, timeout() and realtime_timeout(), 293*87a18d3fSMadhavan Venkataraman * must pass CALLOUT_FLAG_32BIT to timeout_generic() so that a 32-bit ID 294*87a18d3fSMadhavan Venkataraman * can be generated. 295*87a18d3fSMadhavan Venkataraman */ 296*87a18d3fSMadhavan Venkataraman #ifdef _LP64 297*87a18d3fSMadhavan Venkataraman #define CALLOUT_LEGACY 0 298*87a18d3fSMadhavan Venkataraman #else 299*87a18d3fSMadhavan Venkataraman #define CALLOUT_LEGACY CALLOUT_FLAG_32BIT 300*87a18d3fSMadhavan Venkataraman #endif 301*87a18d3fSMadhavan Venkataraman 302*87a18d3fSMadhavan Venkataraman /* 303*87a18d3fSMadhavan Venkataraman * Callout table flags: 304*87a18d3fSMadhavan Venkataraman * 305*87a18d3fSMadhavan Venkataraman * CALLOUT_TABLE_SUSPENDED 306*87a18d3fSMadhavan Venkataraman * Callout processing on this table has been suspended. 307*87a18d3fSMadhavan Venkataraman */ 308*87a18d3fSMadhavan Venkataraman #define CALLOUT_TABLE_SUSPENDED 0x1UL 309*87a18d3fSMadhavan Venkataraman 310*87a18d3fSMadhavan Venkataraman /* 3117c478bd9Sstevel@tonic-gate * All of the state information associated with a callout table. 3127c478bd9Sstevel@tonic-gate * The fields are ordered with cache performance in mind. 3137c478bd9Sstevel@tonic-gate */ 3147c478bd9Sstevel@tonic-gate typedef struct callout_table { 315*87a18d3fSMadhavan Venkataraman kmutex_t ct_mutex; /* protects all callout state */ 316*87a18d3fSMadhavan Venkataraman callout_t *ct_free; /* free callout structures */ 317*87a18d3fSMadhavan Venkataraman callout_list_t *ct_lfree; /* free callout list structures */ 3187c478bd9Sstevel@tonic-gate callout_id_t ct_short_id; /* most recently issued short-term ID */ 3197c478bd9Sstevel@tonic-gate callout_id_t ct_long_id; /* most recently issued long-term ID */ 320*87a18d3fSMadhavan Venkataraman callout_hash_t *ct_idhash; /* ID hash chains */ 321*87a18d3fSMadhavan Venkataraman callout_hash_t *ct_clhash; /* callout list hash */ 322*87a18d3fSMadhavan Venkataraman kstat_named_t *ct_kstat_data; /* callout kstat data */ 323*87a18d3fSMadhavan Venkataraman 324*87a18d3fSMadhavan Venkataraman ulong_t ct_flags; /* flags */ 325*87a18d3fSMadhavan Venkataraman cyclic_id_t ct_cyclic; /* cyclic for this table */ 326*87a18d3fSMadhavan Venkataraman hrtime_t *ct_heap; /* callout expiration heap */ 327*87a18d3fSMadhavan Venkataraman ulong_t ct_heap_num; /* occupied slots in the heap */ 328*87a18d3fSMadhavan Venkataraman ulong_t ct_heap_max; /* end of the heap */ 329*87a18d3fSMadhavan Venkataraman kmem_cache_t *ct_cache; /* callout kmem cache */ 330*87a18d3fSMadhavan Venkataraman kmem_cache_t *ct_lcache; /* callout list kmem cache */ 331*87a18d3fSMadhavan Venkataraman callout_id_t ct_gen_id; /* generation based ID */ 332*87a18d3fSMadhavan Venkataraman 333*87a18d3fSMadhavan Venkataraman callout_hash_t ct_expired; /* list of expired callout lists */ 334*87a18d3fSMadhavan Venkataraman taskq_t *ct_taskq; /* taskq to execute normal callouts */ 335*87a18d3fSMadhavan Venkataraman kstat_t *ct_kstats; /* callout kstats */ 336*87a18d3fSMadhavan Venkataraman #ifdef _LP64 337*87a18d3fSMadhavan Venkataraman ulong_t ct_pad[4]; /* cache alignment */ 338*87a18d3fSMadhavan Venkataraman #else 339*87a18d3fSMadhavan Venkataraman ulong_t ct_pad[8]; /* cache alignment */ 340*87a18d3fSMadhavan Venkataraman #endif 3417c478bd9Sstevel@tonic-gate } callout_table_t; 3427c478bd9Sstevel@tonic-gate 343*87a18d3fSMadhavan Venkataraman /* 344*87a18d3fSMadhavan Venkataraman * Short hand definitions for the callout kstats. 345*87a18d3fSMadhavan Venkataraman */ 346*87a18d3fSMadhavan Venkataraman #define ct_timeouts \ 347*87a18d3fSMadhavan Venkataraman ct_kstat_data[CALLOUT_TIMEOUTS].value.ui64 348*87a18d3fSMadhavan Venkataraman #define ct_timeouts_pending \ 349*87a18d3fSMadhavan Venkataraman ct_kstat_data[CALLOUT_TIMEOUTS_PENDING].value.ui64 350*87a18d3fSMadhavan Venkataraman #define ct_untimeouts_unexpired \ 351*87a18d3fSMadhavan Venkataraman ct_kstat_data[CALLOUT_UNTIMEOUTS_UNEXPIRED].value.ui64 352*87a18d3fSMadhavan Venkataraman #define ct_untimeouts_executing \ 353*87a18d3fSMadhavan Venkataraman ct_kstat_data[CALLOUT_UNTIMEOUTS_EXECUTING].value.ui64 354*87a18d3fSMadhavan Venkataraman #define ct_untimeouts_expired \ 355*87a18d3fSMadhavan Venkataraman ct_kstat_data[CALLOUT_UNTIMEOUTS_EXPIRED].value.ui64 356*87a18d3fSMadhavan Venkataraman #define ct_expirations \ 357*87a18d3fSMadhavan Venkataraman ct_kstat_data[CALLOUT_EXPIRATIONS].value.ui64 358*87a18d3fSMadhavan Venkataraman #define ct_allocations \ 359*87a18d3fSMadhavan Venkataraman ct_kstat_data[CALLOUT_ALLOCATIONS].value.ui64 360*87a18d3fSMadhavan Venkataraman 361*87a18d3fSMadhavan Venkataraman #define CALLOUT_CHUNK 128 362*87a18d3fSMadhavan Venkataraman 363*87a18d3fSMadhavan Venkataraman #define CALLOUT_HEAP_PARENT(index) (((index) - 1) >> 1) 364*87a18d3fSMadhavan Venkataraman #define CALLOUT_HEAP_RIGHT(index) (((index) + 1) << 1) 365*87a18d3fSMadhavan Venkataraman #define CALLOUT_HEAP_LEFT(index) ((((index) + 1) << 1) - 1) 366*87a18d3fSMadhavan Venkataraman 367*87a18d3fSMadhavan Venkataraman #define CALLOUT_CYCLIC_HANDLER(t) \ 368*87a18d3fSMadhavan Venkataraman ((t == CALLOUT_REALTIME) ? callout_realtime : callout_normal) 369*87a18d3fSMadhavan Venkataraman 370*87a18d3fSMadhavan Venkataraman /* 371*87a18d3fSMadhavan Venkataraman * We define a blanket minimum resolution for callouts of 1 millisecond. 372*87a18d3fSMadhavan Venkataraman * 1 millisecond is a safe value as it is already supported when the clock 373*87a18d3fSMadhavan Venkataraman * resolution is set to high. 374*87a18d3fSMadhavan Venkataraman */ 375*87a18d3fSMadhavan Venkataraman #define CALLOUT_MIN_RESOLUTION 1000000ULL 376*87a18d3fSMadhavan Venkataraman #define CALLOUT_TCP_RESOLUTION 10000000ULL 377*87a18d3fSMadhavan Venkataraman 378*87a18d3fSMadhavan Venkataraman #define CALLOUT_ALIGN 64 /* cache line size */ 379*87a18d3fSMadhavan Venkataraman 3807c478bd9Sstevel@tonic-gate extern void callout_init(void); 381*87a18d3fSMadhavan Venkataraman extern void membar_sync(void); 382*87a18d3fSMadhavan Venkataraman extern void callout_cpu_configure(cpu_t *); 383*87a18d3fSMadhavan Venkataraman extern void callout_cpu_online(cpu_t *); 384*87a18d3fSMadhavan Venkataraman extern void callout_cpu_init(cpu_t *); 385*87a18d3fSMadhavan Venkataraman extern void callout_hrestime(void); 3867c478bd9Sstevel@tonic-gate #endif 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate #ifdef __cplusplus 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate #endif 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate #endif /* _SYS_CALLO_H */ 393