10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 56422Sqiao * Common Development and Distribution License (the "License"). 66422Sqiao * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 220Sstevel@tonic-gate /* All Rights Reserved */ 230Sstevel@tonic-gate 240Sstevel@tonic-gate 250Sstevel@tonic-gate /* 2611745SMadhavan.Venkataraman@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 276422Sqiao * Use is subject to license terms. 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #ifndef _SYS_CALLO_H 310Sstevel@tonic-gate #define _SYS_CALLO_H 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <sys/t_lock.h> 340Sstevel@tonic-gate #include <sys/taskq.h> 358048SMadhavan.Venkataraman@Sun.COM #include <sys/lgrp.h> 368048SMadhavan.Venkataraman@Sun.COM #include <sys/processor.h> 378048SMadhavan.Venkataraman@Sun.COM #include <sys/cyclic.h> 388048SMadhavan.Venkataraman@Sun.COM #include <sys/kstat.h> 398048SMadhavan.Venkataraman@Sun.COM #include <sys/systm.h> 400Sstevel@tonic-gate 410Sstevel@tonic-gate #ifdef __cplusplus 420Sstevel@tonic-gate extern "C" { 430Sstevel@tonic-gate #endif 440Sstevel@tonic-gate 458048SMadhavan.Venkataraman@Sun.COM #ifdef _KERNEL 468048SMadhavan.Venkataraman@Sun.COM 478048SMadhavan.Venkataraman@Sun.COM typedef struct callout_list callout_list_t; 480Sstevel@tonic-gate 490Sstevel@tonic-gate /* 500Sstevel@tonic-gate * The callout mechanism provides general-purpose event scheduling: 510Sstevel@tonic-gate * an arbitrary function is called in a specified amount of time. 528048SMadhavan.Venkataraman@Sun.COM * The expiration time for a callout is kept in its callout list 538048SMadhavan.Venkataraman@Sun.COM * structure. 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate typedef struct callout { 560Sstevel@tonic-gate struct callout *c_idnext; /* next in ID hash, or on freelist */ 570Sstevel@tonic-gate struct callout *c_idprev; /* prev in ID hash */ 588048SMadhavan.Venkataraman@Sun.COM struct callout *c_clnext; /* next in callout list */ 598048SMadhavan.Venkataraman@Sun.COM struct callout *c_clprev; /* prev in callout list */ 600Sstevel@tonic-gate callout_id_t c_xid; /* extended callout ID; see below */ 618048SMadhavan.Venkataraman@Sun.COM callout_list_t *c_list; /* callout list */ 620Sstevel@tonic-gate void (*c_func)(void *); /* function to call */ 630Sstevel@tonic-gate void *c_arg; /* argument to function */ 649039SMadhavan.Venkataraman@Sun.COM kthread_t *c_executor; /* executing thread */ 659039SMadhavan.Venkataraman@Sun.COM kcondvar_t c_done; /* signal callout completion */ 669039SMadhavan.Venkataraman@Sun.COM ushort_t c_waiting; /* untimeout waiting flag */ 670Sstevel@tonic-gate } callout_t; 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* 708048SMadhavan.Venkataraman@Sun.COM * The callout ID (callout_id_t) uniquely identifies a callout. The callout 718048SMadhavan.Venkataraman@Sun.COM * ID is always 64 bits internally. The lower 32 bits contain an ID value. 728048SMadhavan.Venkataraman@Sun.COM * The upper 32 bits contain a generation number and flags. When the ID value 738048SMadhavan.Venkataraman@Sun.COM * wraps the generation number is incremented during ID generation. This 748048SMadhavan.Venkataraman@Sun.COM * protects callers from ID collisions that can happen as a result of the wrap. 758048SMadhavan.Venkataraman@Sun.COM * 768048SMadhavan.Venkataraman@Sun.COM * The kernel internal interface, timeout_generic(), always returns a 778048SMadhavan.Venkataraman@Sun.COM * callout_id_t. But the legacy interfaces, timeout() and realtime_timeout() 788048SMadhavan.Venkataraman@Sun.COM * return a timeout_id_t. On a 64-bit system, timeout_id_t is also 64 bits. 798048SMadhavan.Venkataraman@Sun.COM * So, the full 64-bit ID (sans the flags) can be returned. However, on 32-bit 808048SMadhavan.Venkataraman@Sun.COM * systems, timeout_id_t is 32 bits. So, only the lower 32 bits can be 818048SMadhavan.Venkataraman@Sun.COM * returned. In such cases, a default generation number of 0 is assigned to 828048SMadhavan.Venkataraman@Sun.COM * the legacy IDs. 838048SMadhavan.Venkataraman@Sun.COM * 849334SMadhavan.Venkataraman@Sun.COM * The lower 32-bit ID space is partitioned into two spaces - one for 859334SMadhavan.Venkataraman@Sun.COM * short-term callouts and one for long-term. 868048SMadhavan.Venkataraman@Sun.COM * 878048SMadhavan.Venkataraman@Sun.COM * Here is the bit layout for the callout ID: 880Sstevel@tonic-gate * 899334SMadhavan.Venkataraman@Sun.COM * 63 62 61 ... 32 31 30 29 .. X+1 X ... 1 0 909334SMadhavan.Venkataraman@Sun.COM * ----------------------------------------------------------------------- 919334SMadhavan.Venkataraman@Sun.COM * | Free | Exec | Generation | Long | Counter | ID bits | Table | Type | 929334SMadhavan.Venkataraman@Sun.COM * | | | number | term | High | | number | | 939334SMadhavan.Venkataraman@Sun.COM * ----------------------------------------------------------------------- 949334SMadhavan.Venkataraman@Sun.COM * 959334SMadhavan.Venkataraman@Sun.COM * Free: 969334SMadhavan.Venkataraman@Sun.COM * This bit indicates that this callout has been freed. This is for 979334SMadhavan.Venkataraman@Sun.COM * debugging purposes. 988048SMadhavan.Venkataraman@Sun.COM * 998048SMadhavan.Venkataraman@Sun.COM * Exec(uting): 1008048SMadhavan.Venkataraman@Sun.COM * This is the executing bit which is only set in the extended callout 1018048SMadhavan.Venkataraman@Sun.COM * ID. This bit indicates that the callout handler is currently being 1028048SMadhavan.Venkataraman@Sun.COM * executed. 1038048SMadhavan.Venkataraman@Sun.COM * 1048048SMadhavan.Venkataraman@Sun.COM * Generation number: 1058048SMadhavan.Venkataraman@Sun.COM * This is the generation part of the ID. 1068048SMadhavan.Venkataraman@Sun.COM * 1078048SMadhavan.Venkataraman@Sun.COM * Long term: 1088048SMadhavan.Venkataraman@Sun.COM * This bit indicates whether this is a short-term or a long-term callout. 1098048SMadhavan.Venkataraman@Sun.COM * The long-term bit exists to address the problem of callout ID collision 1108048SMadhavan.Venkataraman@Sun.COM * on 32-bit systems. This is an issue because the system typically 1118048SMadhavan.Venkataraman@Sun.COM * generates a large number of timeout() requests, which means that callout 1128048SMadhavan.Venkataraman@Sun.COM * IDs eventually get recycled. Most timeouts are very short-lived, so that 1138048SMadhavan.Venkataraman@Sun.COM * ID recycling isn't a problem; but there are a handful of timeouts which 1148048SMadhavan.Venkataraman@Sun.COM * are sufficiently long-lived to see their own IDs reused. We use the 1158048SMadhavan.Venkataraman@Sun.COM * long-term bit to partition the ID namespace into pieces; the short-term 1168048SMadhavan.Venkataraman@Sun.COM * space gets all the heavy traffic and can wrap frequently (i.e., on the 1178048SMadhavan.Venkataraman@Sun.COM * order of a day) with no ill effects; the long-term space gets very little 1188048SMadhavan.Venkataraman@Sun.COM * traffic and thus never wraps. That said, we need to future proof callouts 1198048SMadhavan.Venkataraman@Sun.COM * in case 32-bit systems grow in size and are able to consume callout IDs 1208048SMadhavan.Venkataraman@Sun.COM * at faster rates. So, we should make all the kernel clients that use 1218048SMadhavan.Venkataraman@Sun.COM * callouts to use the internal interface so that they can use IDs outside 1228048SMadhavan.Venkataraman@Sun.COM * of the legacy space with a proper generation number. 1238048SMadhavan.Venkataraman@Sun.COM * 1248048SMadhavan.Venkataraman@Sun.COM * Counter High + ID counter bits: 1258048SMadhavan.Venkataraman@Sun.COM * These bits represent the actual ID bits in the callout ID. 1268048SMadhavan.Venkataraman@Sun.COM * The highest bit of the running counter is always set; this ensures that 1278048SMadhavan.Venkataraman@Sun.COM * the callout ID is always non-zero, thus eliminating the need for an 1288048SMadhavan.Venkataraman@Sun.COM * explicit wrap-around test during ID generation. 1298048SMadhavan.Venkataraman@Sun.COM * 1308048SMadhavan.Venkataraman@Sun.COM * Table number: 1318048SMadhavan.Venkataraman@Sun.COM * These bits carry the table number for the callout table where the callout 1328048SMadhavan.Venkataraman@Sun.COM * is queued. Each CPU has its own callout table. So, the callout tables are 1338048SMadhavan.Venkataraman@Sun.COM * numbered from 0 - (max_ncpus - 1). Because max_ncpus is different on 1348048SMadhavan.Venkataraman@Sun.COM * different systems, the actual number of table number bits will vary 1358048SMadhavan.Venkataraman@Sun.COM * accordingly. And so will the ID counter bits. 1368048SMadhavan.Venkataraman@Sun.COM * 1378048SMadhavan.Venkataraman@Sun.COM * Type: 1388048SMadhavan.Venkataraman@Sun.COM * This bit represents the callout (table) type. Each CPU has one realtime 1398048SMadhavan.Venkataraman@Sun.COM * and one normal callout table. 1400Sstevel@tonic-gate */ 14111745SMadhavan.Venkataraman@Sun.COM #define CALLOUT_ID_FREE 0x8000000000000000ULL 1429334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_EXECUTING 0x4000000000000000ULL 14311745SMadhavan.Venkataraman@Sun.COM #define CALLOUT_ID_FLAGS (CALLOUT_ID_FREE | CALLOUT_EXECUTING) 1449334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_ID_MASK ~CALLOUT_ID_FLAGS 1458048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_GENERATION_LOW 0x100000000ULL 1468048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LONGTERM 0x80000000 1478048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_COUNTER_HIGH 0x40000000 1480Sstevel@tonic-gate #define CALLOUT_TYPE_BITS 1 1490Sstevel@tonic-gate #define CALLOUT_NTYPES (1 << CALLOUT_TYPE_BITS) 1508048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_TYPE_MASK (CALLOUT_NTYPES - 1) 1518048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_COUNTER_SHIFT callout_table_bits 1528048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_TABLE(t, f) (((f) << CALLOUT_TYPE_BITS) | (t)) 1538048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_TABLE_NUM(ct) ((ct) - callout_table) 1548048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_TABLE_SEQID(ct) (CALLOUT_TABLE_NUM(ct) >> CALLOUT_TYPE_BITS) 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate /* 1570Sstevel@tonic-gate * We assume that during any period of CALLOUT_LONGTERM_TICKS ticks, at most 1588048SMadhavan.Venkataraman@Sun.COM * (CALLOUT_COUNTER_HIGH / callout_counter_low) callouts will be generated. 1590Sstevel@tonic-gate */ 1608048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LONGTERM_TICKS 0x4000UL 1618048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_BUCKET_SHIFT 9 1628048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_BUCKETS (1 << CALLOUT_BUCKET_SHIFT) 1630Sstevel@tonic-gate #define CALLOUT_BUCKET_MASK (CALLOUT_BUCKETS - 1) 1640Sstevel@tonic-gate #define CALLOUT_HASH(x) ((x) & CALLOUT_BUCKET_MASK) 1650Sstevel@tonic-gate #define CALLOUT_IDHASH(x) CALLOUT_HASH((x) >> CALLOUT_COUNTER_SHIFT) 1668048SMadhavan.Venkataraman@Sun.COM /* 1678048SMadhavan.Venkataraman@Sun.COM * The multiply by 0 and 1 below are cosmetic. Just to align things better 1688048SMadhavan.Venkataraman@Sun.COM * and make it more readable. The multiplications will be done at compile 1698048SMadhavan.Venkataraman@Sun.COM * time. 1708048SMadhavan.Venkataraman@Sun.COM */ 1718048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_CLHASH(x) \ 1728048SMadhavan.Venkataraman@Sun.COM CALLOUT_HASH( \ 1738048SMadhavan.Venkataraman@Sun.COM ((x)>>(CALLOUT_BUCKET_SHIFT*0)) ^ \ 1748048SMadhavan.Venkataraman@Sun.COM ((x)>>(CALLOUT_BUCKET_SHIFT*1)) ^ \ 1758048SMadhavan.Venkataraman@Sun.COM ((x)>>(CALLOUT_BUCKET_SHIFT*2)) ^ \ 1768048SMadhavan.Venkataraman@Sun.COM ((x)>>(CALLOUT_BUCKET_SHIFT*3))) 1778048SMadhavan.Venkataraman@Sun.COM 1788048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_ID_TO_TABLE(id) ((id) & callout_table_mask) 1798048SMadhavan.Venkataraman@Sun.COM 1808048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_SHORT_ID(table) \ 1818048SMadhavan.Venkataraman@Sun.COM ((callout_id_t)(table) | CALLOUT_COUNTER_HIGH) 1828048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LONG_ID(table) \ 1838048SMadhavan.Venkataraman@Sun.COM (CALLOUT_SHORT_ID(table) | CALLOUT_LONGTERM) 1840Sstevel@tonic-gate 1859334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_THREADS 2 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate #define CALLOUT_REALTIME 0 /* realtime callout type */ 1880Sstevel@tonic-gate #define CALLOUT_NORMAL 1 /* normal callout type */ 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate /* 1918048SMadhavan.Venkataraman@Sun.COM * callout_t's are cache-aligned structures allocated from kmem caches. One kmem 1928048SMadhavan.Venkataraman@Sun.COM * cache is created per lgrp and is shared by all CPUs in that lgrp. Benefits: 1938048SMadhavan.Venkataraman@Sun.COM * - cache pages are mapped only in the TLBs of the CPUs of the lgrp 1948048SMadhavan.Venkataraman@Sun.COM * - data in cache pages is present only in those CPU caches 1958048SMadhavan.Venkataraman@Sun.COM * - memory access performance improves with locality-awareness in kmem 1968048SMadhavan.Venkataraman@Sun.COM * 1978048SMadhavan.Venkataraman@Sun.COM * The following structure is used to manage per-lgroup kmem caches. 1988048SMadhavan.Venkataraman@Sun.COM * 1998048SMadhavan.Venkataraman@Sun.COM * NOTE: Free callout_t's go to a callout table's freelist. CPUs map to callout 2008048SMadhavan.Venkataraman@Sun.COM * tables via their sequence IDs, not CPU IDs. DR operations can cause a 2018048SMadhavan.Venkataraman@Sun.COM * free list to have callouts from multiple lgrp caches. This takes away some 2028048SMadhavan.Venkataraman@Sun.COM * performance, but is no worse than if we did not use lgrp caches at all. 2038048SMadhavan.Venkataraman@Sun.COM */ 2048048SMadhavan.Venkataraman@Sun.COM typedef struct callout_cache { 2058048SMadhavan.Venkataraman@Sun.COM struct callout_cache *cc_next; /* link in the global list */ 2068048SMadhavan.Venkataraman@Sun.COM lgrp_handle_t cc_hand; /* lgroup handle */ 2078048SMadhavan.Venkataraman@Sun.COM kmem_cache_t *cc_cache; /* kmem cache pointer */ 2088048SMadhavan.Venkataraman@Sun.COM kmem_cache_t *cc_lcache; /* kmem cache pointer */ 2098048SMadhavan.Venkataraman@Sun.COM } callout_cache_t; 2108048SMadhavan.Venkataraman@Sun.COM 2118048SMadhavan.Venkataraman@Sun.COM /* 2128048SMadhavan.Venkataraman@Sun.COM * The callout hash structure is used for queueing both callouts and 2138048SMadhavan.Venkataraman@Sun.COM * callout lists. That is why the fields are declared as void *. 2148048SMadhavan.Venkataraman@Sun.COM */ 2158048SMadhavan.Venkataraman@Sun.COM typedef struct callout_hash { 2168048SMadhavan.Venkataraman@Sun.COM void *ch_head; 2178048SMadhavan.Venkataraman@Sun.COM void *ch_tail; 2188048SMadhavan.Venkataraman@Sun.COM } callout_hash_t; 2198048SMadhavan.Venkataraman@Sun.COM 2209334SMadhavan.Venkataraman@Sun.COM /* 2219334SMadhavan.Venkataraman@Sun.COM * CALLOUT_LIST_FLAG_FREE 2229334SMadhavan.Venkataraman@Sun.COM * Callout list is free. 2239334SMadhavan.Venkataraman@Sun.COM * CALLOUT_LIST_FLAG_ABSOLUTE 2249334SMadhavan.Venkataraman@Sun.COM * Callout list contains absolute timers. 2259334SMadhavan.Venkataraman@Sun.COM * CALLOUT_LIST_FLAG_HRESTIME 2269334SMadhavan.Venkataraman@Sun.COM * Callout list contains hrestime timers. 2279334SMadhavan.Venkataraman@Sun.COM * CALLOUT_LIST_FLAG_NANO 2289334SMadhavan.Venkataraman@Sun.COM * Callout list contains 1-nanosecond resolution callouts. 22911745SMadhavan.Venkataraman@Sun.COM * CALLOUT_LIST_FLAG_HEAPED 23011745SMadhavan.Venkataraman@Sun.COM * Callout list is present in the callout heap. 23111745SMadhavan.Venkataraman@Sun.COM * CALLOUT_LIST_FLAG_QUEUED 23211745SMadhavan.Venkataraman@Sun.COM * Callout list is present in the callout queue. 2339334SMadhavan.Venkataraman@Sun.COM */ 2349334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LIST_FLAG_FREE 0x1 2359334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LIST_FLAG_ABSOLUTE 0x2 2369334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LIST_FLAG_HRESTIME 0x4 2379334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LIST_FLAG_NANO 0x8 23811745SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LIST_FLAG_HEAPED 0x10 23911745SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LIST_FLAG_QUEUED 0x20 2409334SMadhavan.Venkataraman@Sun.COM 2418048SMadhavan.Venkataraman@Sun.COM struct callout_list { 2428048SMadhavan.Venkataraman@Sun.COM callout_list_t *cl_next; /* next in clhash */ 2438048SMadhavan.Venkataraman@Sun.COM callout_list_t *cl_prev; /* prev in clhash */ 2448048SMadhavan.Venkataraman@Sun.COM hrtime_t cl_expiration; /* expiration for callouts in list */ 2458048SMadhavan.Venkataraman@Sun.COM callout_hash_t cl_callouts; /* list of callouts */ 2469039SMadhavan.Venkataraman@Sun.COM int cl_flags; /* callout flags */ 2478048SMadhavan.Venkataraman@Sun.COM }; 2488048SMadhavan.Venkataraman@Sun.COM 2498048SMadhavan.Venkataraman@Sun.COM /* 2509334SMadhavan.Venkataraman@Sun.COM * Callout heap element. Each element in the heap stores the expiration 2519334SMadhavan.Venkataraman@Sun.COM * as well as the corresponding callout list. This is to avoid a lookup 2529334SMadhavan.Venkataraman@Sun.COM * of the callout list when the heap is processed. Because we store the 2539334SMadhavan.Venkataraman@Sun.COM * callout list pointer in the heap element, we have to always remove 2549334SMadhavan.Venkataraman@Sun.COM * a heap element and its callout list together. We cannot remove one 2559334SMadhavan.Venkataraman@Sun.COM * without the other. 25611745SMadhavan.Venkataraman@Sun.COM * 25711745SMadhavan.Venkataraman@Sun.COM * This structure's size must be a power of two because we want an 25811745SMadhavan.Venkataraman@Sun.COM * integral number of these to fit into a page. 2599334SMadhavan.Venkataraman@Sun.COM */ 2609334SMadhavan.Venkataraman@Sun.COM typedef struct callout_heap { 2619334SMadhavan.Venkataraman@Sun.COM hrtime_t ch_expiration; 2629334SMadhavan.Venkataraman@Sun.COM callout_list_t *ch_list; 263*11950SMadhavan.Venkataraman@Sun.COM #ifndef _LP64 264*11950SMadhavan.Venkataraman@Sun.COM char ch_pad[4]; /* pad to power of 2 */ 265*11950SMadhavan.Venkataraman@Sun.COM #endif 2669334SMadhavan.Venkataraman@Sun.COM } callout_heap_t; 2679334SMadhavan.Venkataraman@Sun.COM 2689334SMadhavan.Venkataraman@Sun.COM /* 2699334SMadhavan.Venkataraman@Sun.COM * When the heap contains too many empty callout lists, it needs to be 2709334SMadhavan.Venkataraman@Sun.COM * cleaned up. The decision to clean up the heap is a function of the 2719334SMadhavan.Venkataraman@Sun.COM * number of empty entries and the heap size. Also, we don't want to 2729334SMadhavan.Venkataraman@Sun.COM * clean up small heaps. 2739334SMadhavan.Venkataraman@Sun.COM */ 2749334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_MIN_REAP (CALLOUT_BUCKETS >> 3) 2759334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_CLEANUP(ct) ((ct->ct_nreap >= callout_min_reap) && \ 2769334SMadhavan.Venkataraman@Sun.COM (ct->ct_nreap >= (ct->ct_heap_num >> 1))) 2779334SMadhavan.Venkataraman@Sun.COM 2789334SMadhavan.Venkataraman@Sun.COM /* 2798048SMadhavan.Venkataraman@Sun.COM * Per-callout table kstats. 2808048SMadhavan.Venkataraman@Sun.COM * 2818048SMadhavan.Venkataraman@Sun.COM * CALLOUT_TIMEOUTS 2828048SMadhavan.Venkataraman@Sun.COM * Callouts created since boot. 2838048SMadhavan.Venkataraman@Sun.COM * CALLOUT_TIMEOUTS_PENDING 2848048SMadhavan.Venkataraman@Sun.COM * Number of outstanding callouts. 2858048SMadhavan.Venkataraman@Sun.COM * CALLOUT_UNTIMEOUTS_UNEXPIRED 2868048SMadhavan.Venkataraman@Sun.COM * Number of cancelled callouts that have not expired. 2878048SMadhavan.Venkataraman@Sun.COM * CALLOUT_UNTIMEOUTS_EXECUTING 2888048SMadhavan.Venkataraman@Sun.COM * Number of cancelled callouts that were executing at the time of 2898048SMadhavan.Venkataraman@Sun.COM * cancellation. 2908048SMadhavan.Venkataraman@Sun.COM * CALLOUT_UNTIMEOUTS_EXPIRED 2918048SMadhavan.Venkataraman@Sun.COM * Number of cancelled callouts that had already expired at the time 2928048SMadhavan.Venkataraman@Sun.COM * of cancellations. 2938048SMadhavan.Venkataraman@Sun.COM * CALLOUT_EXPIRATIONS 2948048SMadhavan.Venkataraman@Sun.COM * Number of callouts that expired. 2958048SMadhavan.Venkataraman@Sun.COM * CALLOUT_ALLOCATIONS 2968048SMadhavan.Venkataraman@Sun.COM * Number of callout structures allocated. 2979334SMadhavan.Venkataraman@Sun.COM * CALLOUT_CLEANUPS 2989334SMadhavan.Venkataraman@Sun.COM * Number of times a callout table is cleaned up. 2998048SMadhavan.Venkataraman@Sun.COM */ 3008048SMadhavan.Venkataraman@Sun.COM typedef enum callout_stat_type { 3018048SMadhavan.Venkataraman@Sun.COM CALLOUT_TIMEOUTS, 3028048SMadhavan.Venkataraman@Sun.COM CALLOUT_TIMEOUTS_PENDING, 3038048SMadhavan.Venkataraman@Sun.COM CALLOUT_UNTIMEOUTS_UNEXPIRED, 3048048SMadhavan.Venkataraman@Sun.COM CALLOUT_UNTIMEOUTS_EXECUTING, 3058048SMadhavan.Venkataraman@Sun.COM CALLOUT_UNTIMEOUTS_EXPIRED, 3068048SMadhavan.Venkataraman@Sun.COM CALLOUT_EXPIRATIONS, 3078048SMadhavan.Venkataraman@Sun.COM CALLOUT_ALLOCATIONS, 3089334SMadhavan.Venkataraman@Sun.COM CALLOUT_CLEANUPS, 3098048SMadhavan.Venkataraman@Sun.COM CALLOUT_NUM_STATS 3108048SMadhavan.Venkataraman@Sun.COM } callout_stat_type_t; 3118048SMadhavan.Venkataraman@Sun.COM 3128048SMadhavan.Venkataraman@Sun.COM /* 3138048SMadhavan.Venkataraman@Sun.COM * Callout flags: 3148048SMadhavan.Venkataraman@Sun.COM * 3158048SMadhavan.Venkataraman@Sun.COM * CALLOUT_FLAG_ROUNDUP 3169039SMadhavan.Venkataraman@Sun.COM * Roundup the expiration time to the next resolution boundary. 3178048SMadhavan.Venkataraman@Sun.COM * If this flag is not specified, the expiration time is rounded down. 3188048SMadhavan.Venkataraman@Sun.COM * CALLOUT_FLAG_ABSOLUTE 3198048SMadhavan.Venkataraman@Sun.COM * Normally, the expiration passed to the timeout API functions is an 3208048SMadhavan.Venkataraman@Sun.COM * expiration interval. If this flag is specified, then it is 3218048SMadhavan.Venkataraman@Sun.COM * interpreted as the expiration time itself. 3228048SMadhavan.Venkataraman@Sun.COM * CALLOUT_FLAG_HRESTIME 3238048SMadhavan.Venkataraman@Sun.COM * Normally, callouts are not affected by changes to system time 3248048SMadhavan.Venkataraman@Sun.COM * (hrestime). This flag is used to create a callout that is affected 3259039SMadhavan.Venkataraman@Sun.COM * by system time. If system time changes, these timers must be 3269039SMadhavan.Venkataraman@Sun.COM * handled in a special way (see callout.c). These are used by condition 3279039SMadhavan.Venkataraman@Sun.COM * variables and LWP timers that need this behavior. 3288048SMadhavan.Venkataraman@Sun.COM * CALLOUT_FLAG_32BIT 3298048SMadhavan.Venkataraman@Sun.COM * Legacy interfaces timeout() and realtime_timeout() pass this flag 3308048SMadhavan.Venkataraman@Sun.COM * to timeout_generic() to indicate that a 32-bit ID should be allocated. 3318048SMadhavan.Venkataraman@Sun.COM */ 3328048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_FLAG_ROUNDUP 0x1 3338048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_FLAG_ABSOLUTE 0x2 3348048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_FLAG_HRESTIME 0x4 3358048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_FLAG_32BIT 0x8 3368048SMadhavan.Venkataraman@Sun.COM 3378048SMadhavan.Venkataraman@Sun.COM /* 3388048SMadhavan.Venkataraman@Sun.COM * On 32-bit systems, the legacy interfaces, timeout() and realtime_timeout(), 3398048SMadhavan.Venkataraman@Sun.COM * must pass CALLOUT_FLAG_32BIT to timeout_generic() so that a 32-bit ID 3408048SMadhavan.Venkataraman@Sun.COM * can be generated. 3418048SMadhavan.Venkataraman@Sun.COM */ 3428048SMadhavan.Venkataraman@Sun.COM #ifdef _LP64 3438048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LEGACY 0 3448048SMadhavan.Venkataraman@Sun.COM #else 3458048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_LEGACY CALLOUT_FLAG_32BIT 3468048SMadhavan.Venkataraman@Sun.COM #endif 3478048SMadhavan.Venkataraman@Sun.COM 3488048SMadhavan.Venkataraman@Sun.COM /* 3490Sstevel@tonic-gate * All of the state information associated with a callout table. 3500Sstevel@tonic-gate * The fields are ordered with cache performance in mind. 3510Sstevel@tonic-gate */ 3520Sstevel@tonic-gate typedef struct callout_table { 3538048SMadhavan.Venkataraman@Sun.COM kmutex_t ct_mutex; /* protects all callout state */ 3548048SMadhavan.Venkataraman@Sun.COM callout_t *ct_free; /* free callout structures */ 3558048SMadhavan.Venkataraman@Sun.COM callout_list_t *ct_lfree; /* free callout list structures */ 3560Sstevel@tonic-gate callout_id_t ct_short_id; /* most recently issued short-term ID */ 3570Sstevel@tonic-gate callout_id_t ct_long_id; /* most recently issued long-term ID */ 3588048SMadhavan.Venkataraman@Sun.COM callout_hash_t *ct_idhash; /* ID hash chains */ 3598048SMadhavan.Venkataraman@Sun.COM callout_hash_t *ct_clhash; /* callout list hash */ 3608048SMadhavan.Venkataraman@Sun.COM kstat_named_t *ct_kstat_data; /* callout kstat data */ 3618048SMadhavan.Venkataraman@Sun.COM 3628566SMadhavan.Venkataraman@Sun.COM uint_t ct_type; /* callout table type */ 3638566SMadhavan.Venkataraman@Sun.COM uint_t ct_suspend; /* suspend count */ 3648048SMadhavan.Venkataraman@Sun.COM cyclic_id_t ct_cyclic; /* cyclic for this table */ 3659334SMadhavan.Venkataraman@Sun.COM callout_heap_t *ct_heap; /* callout expiration heap */ 3668048SMadhavan.Venkataraman@Sun.COM ulong_t ct_heap_num; /* occupied slots in the heap */ 3678048SMadhavan.Venkataraman@Sun.COM ulong_t ct_heap_max; /* end of the heap */ 3688048SMadhavan.Venkataraman@Sun.COM kmem_cache_t *ct_cache; /* callout kmem cache */ 3698048SMadhavan.Venkataraman@Sun.COM kmem_cache_t *ct_lcache; /* callout list kmem cache */ 3708048SMadhavan.Venkataraman@Sun.COM callout_id_t ct_gen_id; /* generation based ID */ 3718048SMadhavan.Venkataraman@Sun.COM 3728048SMadhavan.Venkataraman@Sun.COM callout_hash_t ct_expired; /* list of expired callout lists */ 3738048SMadhavan.Venkataraman@Sun.COM taskq_t *ct_taskq; /* taskq to execute normal callouts */ 3748048SMadhavan.Venkataraman@Sun.COM kstat_t *ct_kstats; /* callout kstats */ 3759334SMadhavan.Venkataraman@Sun.COM int ct_nreap; /* # heap entries that need reaping */ 37611745SMadhavan.Venkataraman@Sun.COM cyclic_id_t ct_qcyclic; /* cyclic for the callout queue */ 37711745SMadhavan.Venkataraman@Sun.COM callout_hash_t ct_queue; /* overflow queue of callouts */ 37811745SMadhavan.Venkataraman@Sun.COM #ifndef _LP64 37911745SMadhavan.Venkataraman@Sun.COM char ct_pad[12]; /* cache alignment */ 3808048SMadhavan.Venkataraman@Sun.COM #endif 38111745SMadhavan.Venkataraman@Sun.COM /* 38211745SMadhavan.Venkataraman@Sun.COM * This structure should be aligned to a 64-byte (cache-line) 38311745SMadhavan.Venkataraman@Sun.COM * boundary. Make sure the padding is right for 32-bit as well 38411745SMadhavan.Venkataraman@Sun.COM * as 64-bit kernels. 38511745SMadhavan.Venkataraman@Sun.COM */ 3860Sstevel@tonic-gate } callout_table_t; 3870Sstevel@tonic-gate 3888048SMadhavan.Venkataraman@Sun.COM /* 3898048SMadhavan.Venkataraman@Sun.COM * Short hand definitions for the callout kstats. 3908048SMadhavan.Venkataraman@Sun.COM */ 3918048SMadhavan.Venkataraman@Sun.COM #define ct_timeouts \ 3928048SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_TIMEOUTS].value.ui64 3938048SMadhavan.Venkataraman@Sun.COM #define ct_timeouts_pending \ 3948048SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_TIMEOUTS_PENDING].value.ui64 3958048SMadhavan.Venkataraman@Sun.COM #define ct_untimeouts_unexpired \ 3968048SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_UNTIMEOUTS_UNEXPIRED].value.ui64 3978048SMadhavan.Venkataraman@Sun.COM #define ct_untimeouts_executing \ 3988048SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_UNTIMEOUTS_EXECUTING].value.ui64 3998048SMadhavan.Venkataraman@Sun.COM #define ct_untimeouts_expired \ 4008048SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_UNTIMEOUTS_EXPIRED].value.ui64 4018048SMadhavan.Venkataraman@Sun.COM #define ct_expirations \ 4028048SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_EXPIRATIONS].value.ui64 4038048SMadhavan.Venkataraman@Sun.COM #define ct_allocations \ 4048048SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_ALLOCATIONS].value.ui64 4059334SMadhavan.Venkataraman@Sun.COM #define ct_cleanups \ 4069334SMadhavan.Venkataraman@Sun.COM ct_kstat_data[CALLOUT_CLEANUPS].value.ui64 4078048SMadhavan.Venkataraman@Sun.COM 40811745SMadhavan.Venkataraman@Sun.COM /* 40911745SMadhavan.Venkataraman@Sun.COM * CALLOUT_CHUNK is the minimum initial size of each heap, and the amount 41011745SMadhavan.Venkataraman@Sun.COM * by which a full heap is expanded to make room for new entries. 41111745SMadhavan.Venkataraman@Sun.COM */ 41211745SMadhavan.Venkataraman@Sun.COM #define CALLOUT_CHUNK (PAGESIZE / sizeof (callout_heap_t)) 41311745SMadhavan.Venkataraman@Sun.COM 41411745SMadhavan.Venkataraman@Sun.COM /* 41511745SMadhavan.Venkataraman@Sun.COM * CALLOUT_MIN_HEAP_SIZE defines the minimum size for the callout heap for 41611745SMadhavan.Venkataraman@Sun.COM * the whole system. 41711745SMadhavan.Venkataraman@Sun.COM */ 41811745SMadhavan.Venkataraman@Sun.COM #define CALLOUT_MIN_HEAP_SIZE (64 * 1024 * sizeof (callout_heap_t)) 41911745SMadhavan.Venkataraman@Sun.COM 42011745SMadhavan.Venkataraman@Sun.COM /* 42111745SMadhavan.Venkataraman@Sun.COM * CALLOUT_MEM_FRACTION defines the fraction of available physical memory that 42211745SMadhavan.Venkataraman@Sun.COM * can be allocated towards the callout heap for the whole system. 42311745SMadhavan.Venkataraman@Sun.COM */ 42411745SMadhavan.Venkataraman@Sun.COM #define CALLOUT_MEM_FRACTION 4096 4258048SMadhavan.Venkataraman@Sun.COM 4268048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_HEAP_PARENT(index) (((index) - 1) >> 1) 4278048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_HEAP_RIGHT(index) (((index) + 1) << 1) 4288048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_HEAP_LEFT(index) ((((index) + 1) << 1) - 1) 4298048SMadhavan.Venkataraman@Sun.COM 4308048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_TCP_RESOLUTION 10000000ULL 4318048SMadhavan.Venkataraman@Sun.COM 4328048SMadhavan.Venkataraman@Sun.COM #define CALLOUT_ALIGN 64 /* cache line size */ 4338048SMadhavan.Venkataraman@Sun.COM 4348566SMadhavan.Venkataraman@Sun.COM #ifdef _LP64 4358566SMadhavan.Venkataraman@Sun.COM #define CALLOUT_MAX_TICKS NSEC_TO_TICK(CY_INFINITY); 4368566SMadhavan.Venkataraman@Sun.COM #else 4378566SMadhavan.Venkataraman@Sun.COM #define CALLOUT_MAX_TICKS LONG_MAX 4388566SMadhavan.Venkataraman@Sun.COM #endif 4398566SMadhavan.Venkataraman@Sun.COM 4409334SMadhavan.Venkataraman@Sun.COM #define CALLOUT_TOLERANCE 200000 /* nanoseconds */ 4419334SMadhavan.Venkataraman@Sun.COM 4428048SMadhavan.Venkataraman@Sun.COM extern void callout_init(void); 4438048SMadhavan.Venkataraman@Sun.COM extern void membar_sync(void); 4448048SMadhavan.Venkataraman@Sun.COM extern void callout_cpu_online(cpu_t *); 4458566SMadhavan.Venkataraman@Sun.COM extern void callout_cpu_offline(cpu_t *); 4468048SMadhavan.Venkataraman@Sun.COM extern void callout_hrestime(void); 4478566SMadhavan.Venkataraman@Sun.COM 4480Sstevel@tonic-gate #endif 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate #ifdef __cplusplus 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate #endif 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate #endif /* _SYS_CALLO_H */ 455