Home | History | Annotate | Download | only in cyclic

Lines Matching refs:cyclic

1 /*	$NetBSD: cyclic.c,v 1.10 2024/09/08 09:36:46 rillig Exp $	*/
26 * $FreeBSD: head/sys/cddl/dev/cyclic/cyclic.c 227293 2011-11-07 06:44:47Z ed $
28 * This is a simplified version of the cyclic timer subsystem from
38 * The Cyclic Subsystem
61 * The cyclic subsystem has been designed to take advantage of chip
67 * The cyclic subsystem is a low-level kernel subsystem designed to provide
69 * with existing terms, we dub such an interval timer a "cyclic").
70 * Alternatively, a cyclic may be specified to be "omnipresent", denoting
73 * Cyclic Subsystem Interface Overview
76 * The cyclic subsystem has interfaces with the kernel at-large, with other
78 * resume subsystem) and with the platform (the cyclic backend). Each
82 * The following diagram displays the cyclic subsystem's interfaces to
84 * the large arrow indicating the cyclic subsystem's consumer interface.
97 * | Cyclic subsystem |<----------- Other kernel subsystems
106 * | Cyclic backend |
114 * cyclic_add() <-- Creates a cyclic
115 * cyclic_add_omni() <-- Creates an omnipresent cyclic
116 * cyclic_remove() <-- Removes a cyclic
120 * cyclic_init() <-- Initializes the cyclic subsystem
127 * Cyclic Subsystem Implementation Overview
130 * The cyclic subsystem is designed to minimize interference between cyclics
131 * on different CPUs. Thus, all of the cyclic subsystem's data structures
134 * Each cyc_cpu has a power-of-two sized array of cyclic structures (the
142 * heap is keyed by cyclic expiration time, with parents expiring earlier
148 * compares the root cyclic's expiration time to the current time. If the
150 * cyclic. Upon return from cyclic_expire(), the cyclic's new expiration time
153 * examines the (potentially changed) root cyclic, repeating the
155 * cyclic has an expiration time in the future. This expiration time
158 * shortly after the root cyclic's expiration time.
258 * the cyclic at cyp_cyclics[cyp_heap[number_of_elements]], incrementing
276 * To insert into this heap, we would just need to fill in the cyclic at
284 * because the cyclic does not keep a backpointer into the heap. This makes
291 * a cyclic. Cyclic subsystem consumers are guaranteed that for an arbitrary
292 * time t in the future, their cyclic handler will have been called
306 * on the CPU being resized, but should not affect cyclic operation on other
320 * Cyclic removals should be rare. To simplify the implementation (and to
370 MALLOC_DEFINE(M_CYCLIC, "cyclic", "Cyclic timer subsystem");
496 cyclic_expire(cyc_cpu_t *cpu, cyc_index_t ndx, cyclic_t *cyclic)
498 cyc_func_t handler = cyclic->cy_handler;
499 void *arg = cyclic->cy_arg;
509 * cyclic_fire() is the cyclic subsystem's interrupt handler.
510 * Called by the cyclic backend.
521 * of the cyclic subsystem does not rely on the timeliness of the backend.
536 cyclic_t *cyclic, *cyclics = cpu->cyp_cyclics;
549 cyclic = &cyclics[ndx];
551 ASSERT(!(cyclic->cy_flags & CYF_FREE));
553 if ((exp = cyclic->cy_expire) > now)
556 cyclic_expire(cpu, ndx, cyclic);
559 * If this cyclic will be set to next expire in the distant
562 * a) This is the first firing of a cyclic which had
565 * b) We are tragically late for a cyclic -- most likely
577 exp += cyclic->cy_interval;
580 hrtime_t interval = cyclic->cy_interval;
585 cyclic->cy_expire = exp;
590 * Now we have a cyclic in the root slot which isn't in the past;
691 cyclic_t *cyclic;
708 cyclic = &cpu->cyp_cyclics[ndx];
710 ASSERT(cyclic->cy_flags == CYF_FREE);
711 cyclic->cy_interval = when->cyt_interval;
718 cyclic->cy_expire = (gethrtime() / cyclic->cy_interval + 1) *
719 cyclic->cy_interval;
721 cyclic->cy_expire = when->cyt_when;
724 cyclic->cy_handler = hdlr->cyh_func;
725 cyclic->cy_arg = hdlr->cyh_arg;
726 cyclic->cy_flags = arg->cyx_flags;
729 hrtime_t exp = cyclic->cy_expire;
766 * actually add our cyclic.
786 cyclic_t *cyclic;
792 cyclic = &cpu->cyp_cyclics[ndx];
795 * Grab the current expiration time. If this cyclic is being
797 * will be used when the cyclic is added to the new CPU.
800 arg->cyx_when->cyt_when = cyclic->cy_expire;
801 arg->cyx_when->cyt_interval = cyclic->cy_interval;
810 cyclic->cy_flags = CYF_FREE;
818 panic("attempt to remove non-existent cyclic");
865 cyclic = &cpu->cyp_cyclics[heap[0]];
868 be->cyb_reprogram(bar, cyclic->cy_expire);
912 mtx_init(&cpu->cyp_mtx, "cyclic cpu", NULL, MTX_SPIN);
925 * cyclic subsystem for this CPU is prepared to field interrupts.
1006 * CPU -- the definition of an omnipresent cyclic is that it runs
1020 * The cyclic has been removed from this CPU; time to call the
1040 * associated with the cyclic. If and only if this field is NULL, the
1041 * cyc_id_t is an omnipresent cyclic. Note that cyi_omni_list may be
1042 * NULL for an omnipresent cyclic while the cyclic is being created
1067 * cyclic_add() will create an unbound cyclic with the specified handler and
1068 * interval. The cyclic
1076 * cyc_func_t cyh_func <-- Cyclic handler
1077 * void *cyh_arg <-- Argument to cyclic handler
1087 * is set to 0, the cyclic will start to fire when cyt_interval next
1091 * _not_ explicitly supported by the cyclic subsystem (cyclic_add() will
1096 * For an arbitrary time t in the future, the cyclic handler is guaranteed
1100 * the cyclic handler may be called a finite number of times with an
1103 * The cyclic subsystem will not enforce any lower bound on the interval;
1119 * apply. A cyclic may be added even in the presence of CPUs that have
1120 * not been configured with respect to the cyclic subsystem, but only
1121 * configured CPUs will be eligible to run the new cyclic.
1123 * Cyclic handler's context
1125 * Cyclic handlers will be executed in the interrupt context corresponding
1129 * A cyclic handler may not grab ANY locks held by the caller of any of
1131 * may require blocking on cyclic handler completion.
1132 * Moreover, cyclic handlers may not make any call back into the cyclic
1155 * cyclic_add_omni() will create an omnipresent cyclic with the specified
1180 * The omni cyclic online handler is always called _before_ the omni
1181 * cyclic begins to fire on the specified CPU. As the above argument
1185 * allows the omni cyclic to have maximum flexibility; different CPUs may
1199 * by cyclic handlers. However, omni cyclic online handlers may _not_
1200 * call back into the cyclic subsystem, and should be generally careful
1210 * void * <-- CPU's cyclic argument (that is, value
1214 * The omni cyclic offline handler is always called _after_ the omni
1215 * cyclic has ceased firing on the specified CPU. Its purpose is to
1216 * allow cleanup of any resources dynamically allocated in the omni cyclic
1255 * this cyclic.
1268 * cyclic_remove() will remove the specified cyclic from the system.
1276 * removed cyclic handler has completed execution (this is the same
1278 * need to block, waiting for the removed cyclic to complete execution.
1280 * held across cyclic_remove() that also may be acquired by a cyclic
1291 * grabbed by any cyclic handler. See "Arguments and notes", above.
1339 * It is assumed that cyclic_mp_init() is called some time after cyclic
1387 * Cyclic subsystem initialisation.
1440 DEV_MODULE(cyclic, cyclic_modevent, NULL);
1441 MODULE_VERSION(cyclic, 1);
1442 MODULE_DEPEND(cyclic, opensolaris, 1, 1, 1);
1468 MODULE(MODULE_CLASS_MISC, cyclic, "solaris");