Coherent4.2.10/include/kernel/ddi_cpu.h
/* (-lgl
* Coherent 386 release 4.2
* Copyright (c) 1982, 1993 by Mark Williams Company.
* All rights reserved. May not be copied without permission.
* For copying permission and licensing info, write licensing@mwc.com
-lgl) */
#ifndef __KERNEL_DDI_CPU_H__
#define __KERNEL_DDI_CPU_H__
/*
* This internal header file defines structures and an access procedure for
* DDI/DKI data that is global per CPU. In a multiprocessor system, each
* CPU would have a data region that was separate from all others.
*/
#include <common/ccompat.h>
#include <common/__size.h>
#include <common/_intmask.h>
#include <kernel/_cpuid.h>
#include <kernel/_lock.h>
#include <kernel/ddi_data.h>
#include <sys/debug.h>
/*
* Many DDI/DKI routines specify constraints on the circumstances in which
* they may be called, for example.
* Base level only, eg SV_WAIT ().
* Pass interrupt priority level greater than the current level,
* eg LOCK ().
* Not called from within a streams service routine, eg putbq () with
* a high-priority STREAMS message.
*
* These assertions are important for maintaining system integrity, but it can
* be difficult to detect when these constraints a violated under normal
* circumstances, especially when the probability of failure is expected to
* be low. Therefore, it is important for routines which specify such
* constraints to be able to umambiguously detect constraint violations with
* the highest level of probability possible.
*
* However, the testability of these assertions depends on cooperation from
* a wide range of kernel facilities. In a highly multithreaded system with
* either multiple processors or the ability to suspend interrupt contexts,
* or both, it is necessary to be able to make detailed inquiries about the
* system state to re-establish some of the certainty about system state that
* is lost in the move to gain extra concurrency.
*/
/*
* Returns true if we are at base level or if the system cannot distinguish
* between base and interrupt level; if the system is definitely not at base
* level, returns false.
*/
#define IS_BASE_LEVEL() (ddi_cpu_data ()->dc_int_level == 0)
/*
* Return true if we are at interrupt level or if the system cannot
* distinguish between base and interrupt level; if the system is definitely
* at base level, return false.
*/
#define IS_INTERRUPT_LEVEL() (ddi_cpu_data ()->dc_int_level != 0)
/*
* Enter/exit an interrupt context, maintaining the state variables checked
* for above.
*/
#define __DDI_DKI_ENTER_INTERRUPT() \
((void) (ddi_cpu_data ()->dc_int_level ++))
#define __DDI_DKI_LEAVE_INTERRUPT() \
((void) (ddi_cpu_data ()->dc_int_level --))
/*
* Most of the time we want to include the above in simple assertions.
*/
#define ASSERT_BASE_LEVEL() ASSERT (IS_BASE_LEVEL ())
/*
* Here is a description of the per-CPU data we wish to record.
*
* To deal with lock-hierarchy assertions, we use a table of
* counters instead of maintaining a list of held locks. We do this because
* (1) the nature of shared read/write locks permits even a single CPU to hold
* the same lock multiple times, and (2) although TRYLOCK () and UNLOCK ()
* allow out-of-order acquisition and release we want LOCK () to check
* rigidly the hierarchy assertions. The array of counters is mostly O(1), a
* desirable property.
*
* Although a trace of held locks is not unreasonable, it is difficult to set a
* fixed upper bound on the number of simultaneous locks. Even if we use a
* counter for multiple acquisitions of shared locks, we can potentially need
* as many trace records as allocated locks.
*/
typedef struct ddi_cpu_data dcdata_t;
struct ddi_cpu_data {
/*
* Interrupt-related data are at the front of this structure for easy
* access by hand-coded assembly-language support routines. Same for
* the defer-table stuff.
*/
processorid_t dc_cpuid; /* who are we for? */
intmask_t dc_base_mask; /* interrupt masks */
unsigned char dc_int_level; /* processing interrupts */
/* Deprecated. Do not trust this value. */
unsigned char dc_user_level; /* user level/kernel level */
unsigned char dc_ipl; /* current ipl */
atomic_uchar_t dc_run_timeouts; /* run deferred timeouts */
defer_t dc_defint; /* interrupt-deferred ops */
defer_t dc_defproc; /* process-deferred ops */
unsigned long dc_reserved_1 [4]; /* RESERVED */
__lkhier_t dc_max_hierarchy; /*
* For basic-lock hierarchy
* assertions
*/
__lkhier_t * dc_hierarchy_cnt;
struct pollwait *
dc_pollwait; /* task performing a poll */
char * dc_dynalloc; /* for getting per-cpu data */
char * dc_dynend; /* end of free per-cpu data */
unsigned long dc_idle_ticks; /* idle ticks */
unsigned long dc_idle_time; /* reserved */
unsigned char dc_is_idle; /* non-zero if system idle */
unsigned char dc_reserved_2 [3]; /* RESERVED */
unsigned long dc_reserved_3 [4]; /* RESERVED */
};
__EXTERN_C_BEGIN__
dcdata_t * ddi_cpu_data __PROTO ((void));
#if _DDI_DKI_IMPL
/*
* Functions for the implementation only.
*/
__VOID__ * ddi_cpu_alloc __PROTO ((__size_t _size));
dcdata_t * ddi_cpu_ref __PROTO ((processorid_t _cpu));
void ddi_cpu_unref __PROTO ((dcdata_t * _data));
processorid_t ddi_cpu_id __PROTO ((void));
#endif
__EXTERN_C_END__
extern dcdata_t __ddi_cpu_data [];
extern char __ddi_cpu_dynarea [512];
#define ddi_cpu_data() (__ddi_cpu_data)
#define _USE_IDLE_PROCESS 1
#define __IS_CPU_IDLE() (ddi_cpu_data ()->dc_is_idle)
#define __MARK_CPU_IDLE() ((void) (ddi_cpu_data ()->dc_is_idle = 1))
#define __CLEAR_CPU_IDLE() ((void) (ddi_cpu_data ()->dc_is_idle = 0))
#endif /* ! defined (__KERNEL_DDI_CPU_H__) */