901 lines
20 KiB
C
901 lines
20 KiB
C
/*
|
|
* This file is part of Jehanne.
|
|
*
|
|
* Copyright (C) 2015-2016 Giacomo Tesio <giacomo@tesio.it>
|
|
*
|
|
* Jehanne is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, version 2 of the License.
|
|
*
|
|
* Jehanne is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
typedef struct Alarms Alarms;
|
|
typedef struct AwakeAlarm AwakeAlarm;
|
|
typedef struct Block Block;
|
|
typedef struct Bpool Bpool;
|
|
typedef struct Chan Chan;
|
|
typedef struct Cmdbuf Cmdbuf;
|
|
typedef struct Cmdtab Cmdtab;
|
|
typedef struct Dev Dev;
|
|
typedef struct DevConf DevConf;
|
|
typedef struct Dirtab Dirtab;
|
|
typedef struct Egrp Egrp;
|
|
typedef struct Evalue Evalue;
|
|
typedef struct Fgrp Fgrp;
|
|
typedef struct Ldseg Ldseg;
|
|
typedef struct Log Log;
|
|
typedef struct Logflag Logflag;
|
|
typedef struct Mntcache Mntcache;
|
|
typedef struct Mount Mount;
|
|
typedef struct Mntrpc Mntrpc;
|
|
typedef struct Mntwalk Mntwalk;
|
|
typedef struct Mnt Mnt;
|
|
typedef struct Mhead Mhead;
|
|
typedef struct Next Next;
|
|
typedef struct Note Note;
|
|
typedef struct Path Path;
|
|
typedef struct Perf Perf;
|
|
typedef struct PhysUart PhysUart;
|
|
typedef struct Pgrp Pgrp;
|
|
typedef struct Proc Proc;
|
|
typedef struct Procalloc Procalloc;
|
|
typedef struct Profbuf Profbuf;
|
|
typedef struct Pte Pte;
|
|
typedef struct QLock QLock;
|
|
typedef struct Queue Queue;
|
|
typedef struct Ref Ref;
|
|
typedef struct Rendez Rendez;
|
|
typedef struct Rgrp Rgrp;
|
|
typedef struct RWlock RWlock;
|
|
typedef struct Schedq Schedq;
|
|
typedef struct Sema Sema;
|
|
typedef struct Timer Timer;
|
|
typedef struct Timers Timers;
|
|
typedef struct Uart Uart;
|
|
typedef struct Waitq Waitq;
|
|
typedef struct Walkqid Walkqid;
|
|
typedef struct Watchdog Watchdog;
|
|
typedef int Devgen(Chan*, char*, Dirtab*, int, int, Dir*);
|
|
typedef struct Pool Pool;
|
|
|
|
#pragma incomplete Bpool
|
|
#pragma incomplete DevConf
|
|
#pragma incomplete Mntrpc
|
|
#pragma incomplete Queue
|
|
#pragma incomplete Timers
|
|
|
|
#include <9P2000.h>
|
|
|
|
struct Ref
|
|
{
|
|
int ref;
|
|
};
|
|
|
|
struct Rendez
|
|
{
|
|
Lock l;
|
|
Proc* p;
|
|
};
|
|
|
|
struct QLock
|
|
{
|
|
Lock use; /* to access Qlock structure */
|
|
Proc* head; /* next process waiting for object */
|
|
Proc* tail; /* last process waiting for object */
|
|
uintptr_t qpc; /* pc of the holder */
|
|
int locked; /* flag */
|
|
};
|
|
|
|
struct RWlock
|
|
{
|
|
Lock use;
|
|
Proc* head; /* list of waiting processes */
|
|
Proc* tail;
|
|
uintptr_t wpc; /* pc of writer */
|
|
Proc* wproc; /* writing proc */
|
|
int readers; /* number of readers */
|
|
int writer; /* number of writers */
|
|
};
|
|
|
|
struct Alarms
|
|
{
|
|
QLock ql;
|
|
Proc *head;
|
|
};
|
|
|
|
/*
|
|
* Access types in namec & channel flags
|
|
*/
|
|
enum
|
|
{
|
|
Aaccess, /* as in stat, wstat */
|
|
Abind, /* for left-hand-side of bind */
|
|
Atodir, /* as in chdir */
|
|
Aopen, /* for i/o */
|
|
Amount, /* to be mounted or mounted upon */
|
|
Acreate, /* is to be created */
|
|
Aremove, /* will be removed by caller */
|
|
|
|
COPEN = 0x0001, /* for i/o */
|
|
CMSG = 0x0002, /* the message channel for a mount */
|
|
/*rsc CCREATE = 0x0004,*/ /* permits creation if c->mnt */
|
|
CCEXEC = 0x0008, /* close on exec */
|
|
CFREE = 0x0010, /* not in use */
|
|
CRCLOSE = 0x0020, /* remove on close */
|
|
};
|
|
|
|
/* flag values */
|
|
enum
|
|
{
|
|
BINTR = (1<<0),
|
|
|
|
Bipck = (1<<2), /* ip checksum */
|
|
Budpck = (1<<3), /* udp checksum */
|
|
Btcpck = (1<<4), /* tcp checksum */
|
|
Bpktck = (1<<5), /* packet checksum */
|
|
};
|
|
|
|
struct Block
|
|
{
|
|
Block* next;
|
|
Block* list;
|
|
uint8_t* rp; /* first unconsumed byte */
|
|
uint8_t* wp; /* first empty byte */
|
|
uint8_t* lim; /* 1 past the end of the buffer */
|
|
uint8_t* base; /* start of the buffer */
|
|
void (*free)(Block*);
|
|
uint8_t auxspc[64];
|
|
uint16_t flag;
|
|
uint16_t checksum; /* IP checksum of complete packet (minus media header) */
|
|
uint16_t vlan;
|
|
};
|
|
#define BLEN(s) ((s)->wp - (s)->rp)
|
|
#define BALLOC(s) ((s)->lim - (s)->base)
|
|
|
|
struct Chan
|
|
{
|
|
Lock l;
|
|
Ref r;
|
|
Chan* next; /* allocation */
|
|
Chan* link;
|
|
int64_t offset; /* in fd */
|
|
int64_t devoffset; /* in underlying device; see read */
|
|
Dev* dev;
|
|
uint32_t devno;
|
|
uint64_t mode; /* read/write */
|
|
uint16_t flag;
|
|
Qid qid;
|
|
int fid; /* for devmnt */
|
|
uint32_t iounit; /* chunk size for i/o; 0==default */
|
|
Mhead* umh; /* mount point that derived Chan; used in unionread */
|
|
Chan* umc; /* channel in union; held for union read */
|
|
QLock umqlock; /* serialize unionreads */
|
|
int uri; /* union read index */
|
|
int dri; /* devdirread index */
|
|
uint8_t* dirrock; /* directory entry rock for translations */
|
|
int nrock;
|
|
int mrock;
|
|
QLock rockqlock;
|
|
int ismtpt;
|
|
Mnt* mux; /* Mnt for clients using me for messages */
|
|
union {
|
|
void* aux;
|
|
Qid pgrpid; /* for #p/notepg */
|
|
uint32_t mid; /* for ns in devproc */
|
|
};
|
|
Chan* mchan; /* channel to mounted server */
|
|
Qid mqid; /* qid of root of mount point */
|
|
Path* path;
|
|
};
|
|
|
|
struct Path
|
|
{
|
|
Ref r;
|
|
char* s;
|
|
Chan** mtpt; /* mtpt history */
|
|
int len; /* strlen(s) */
|
|
int alen; /* allocated length of s */
|
|
int mlen; /* number of path elements */
|
|
int malen; /* allocated length of mtpt */
|
|
};
|
|
|
|
struct Dev
|
|
{
|
|
int dc;
|
|
char* name;
|
|
|
|
void (*reset)(void);
|
|
void (*init)(void);
|
|
void (*shutdown)(void);
|
|
Chan* (*attach)(Chan *c, Chan *ac, char *spec, int flags);
|
|
Walkqid*(*walk)(Chan*, Chan*, char**, int);
|
|
long (*stat)(Chan*, uint8_t*, long);
|
|
Chan* (*open)(Chan*, unsigned long);
|
|
Chan* (*create)(Chan*, char*, unsigned long, unsigned long);
|
|
void (*close)(Chan*);
|
|
long (*read)(Chan*, void*, long, int64_t);
|
|
Block* (*bread)(Chan*, long, int64_t);
|
|
long (*write)(Chan*, void*, long, int64_t);
|
|
long (*bwrite)(Chan*, Block*, int64_t);
|
|
void (*remove)(Chan*);
|
|
long (*wstat)(Chan*, uint8_t*, long);
|
|
void (*power)(int); /* power mgt: power(1) => on, power (0) => off */
|
|
int (*config)(int, char*, DevConf*); /* returns 0 on error */
|
|
};
|
|
|
|
struct Dirtab
|
|
{
|
|
char name[KNAMELEN];
|
|
Qid qid;
|
|
int64_t length;
|
|
long perm;
|
|
};
|
|
|
|
struct Walkqid
|
|
{
|
|
Chan *clone;
|
|
int nqid;
|
|
Qid qid[1];
|
|
};
|
|
|
|
enum
|
|
{
|
|
NSMAX = 1000,
|
|
NSLOG = 7,
|
|
NSCACHE = (1<<NSLOG),
|
|
};
|
|
|
|
struct Mntwalk /* state for /proc/#/ns */
|
|
{
|
|
int cddone;
|
|
Mhead* mh;
|
|
Mount* cm;
|
|
};
|
|
|
|
struct Mount
|
|
{
|
|
int mountid;
|
|
Mount* next;
|
|
Mhead* head;
|
|
Mount* copy;
|
|
Mount* order;
|
|
Chan* to; /* channel replacing channel */
|
|
int mflag;
|
|
char *spec;
|
|
};
|
|
|
|
struct Mhead
|
|
{
|
|
Ref r;
|
|
RWlock lock;
|
|
Chan* from; /* channel mounted upon */
|
|
Mount* mount; /* what's mounted upon it */
|
|
Mhead* hash; /* Hash chain */
|
|
};
|
|
|
|
struct Mnt
|
|
{
|
|
Lock l;
|
|
/* references are counted using c->ref; channels on this mount point incref(c->mchan) == Mnt.c */
|
|
Chan* c; /* Channel to file service */
|
|
Proc* rip; /* Reader in progress */
|
|
Mntrpc* queue; /* Queue of pending requests on this channel */
|
|
uint32_t id; /* Multiplexer id for channel check */
|
|
Mnt* list; /* Free list */
|
|
int msize; /* data + IOHDRSZ */
|
|
char* version; /* 9P version */
|
|
Queue* q; /* input queue */
|
|
};
|
|
|
|
enum
|
|
{
|
|
NUser, /* note provided externally */
|
|
NExit, /* deliver note quietly */
|
|
NDebug, /* print debug message */
|
|
};
|
|
|
|
struct Note
|
|
{
|
|
char msg[ERRMAX];
|
|
int flag; /* whether system posted it */
|
|
};
|
|
|
|
enum
|
|
{
|
|
PG_NOFLUSH = 0,
|
|
PG_TXTFLUSH = 1, /* flush dcache and invalidate icache */
|
|
PG_DATFLUSH = 2, /* flush both i & d caches (UNUSED) */
|
|
};
|
|
|
|
#define pagesize(p) (1<<(p)->lg2size)
|
|
|
|
struct Profbuf
|
|
{
|
|
Ref r;
|
|
uint64_t* ticks; /* Tick profile area */
|
|
};
|
|
|
|
struct Sema
|
|
{
|
|
Rendez rend;
|
|
int* addr;
|
|
int waiting;
|
|
Sema* next;
|
|
Sema* prev;
|
|
};
|
|
|
|
#include "../port/umem/umem.h"
|
|
|
|
/* demand loading params of a segment */
|
|
struct Ldseg {
|
|
int64_t memsz;
|
|
int64_t filesz;
|
|
int64_t pg0fileoff;
|
|
uintptr_t pg0vaddr;
|
|
uint32_t pg0off;
|
|
uint32_t pgsz;
|
|
SegmentType type : 3;
|
|
SegPermission permissions : 3;
|
|
SegFlag flags : 2;
|
|
};
|
|
|
|
enum
|
|
{
|
|
RENDHASH = 31, /* Hash to lookup rendezvous tags */
|
|
MNTLOG = 5,
|
|
MNTHASH = 1<<MNTLOG, /* Hash to walk mount table */
|
|
NFD = 100, /* per process file descriptors */
|
|
PGHLOG = 9,
|
|
PGHSIZE = 1<<PGHLOG, /* Page hash for image lookup */
|
|
};
|
|
#define REND(p,s) ((p)->rendhash[(uintptr_t)(s)%RENDHASH])
|
|
#define MOUNTH(p,qid) ((p)->mnthash[(qid).path&((1<<MNTLOG)-1)])
|
|
|
|
struct Pgrp
|
|
{
|
|
Ref r;
|
|
int noattach;
|
|
uint32_t pgrpid;
|
|
QLock debug; /* single access via devproc.c */
|
|
RWlock ns; /* Namespace n read/one write lock */
|
|
Mhead* mnthash[MNTHASH];
|
|
};
|
|
|
|
struct Rgrp
|
|
{
|
|
Lock l;
|
|
Ref r;
|
|
Proc* rendhash[RENDHASH]; /* Rendezvous tag hash */
|
|
};
|
|
|
|
struct Egrp
|
|
{
|
|
Ref r;
|
|
RWlock rwl;
|
|
Evalue** ent;
|
|
int nent;
|
|
int ment;
|
|
uint32_t path; /* qid.path of next Evalue to be allocated */
|
|
uint32_t vers; /* of Egrp */
|
|
};
|
|
|
|
struct Evalue
|
|
{
|
|
char *name;
|
|
char *value;
|
|
int len;
|
|
Evalue *link;
|
|
Qid qid;
|
|
};
|
|
|
|
struct Fgrp
|
|
{
|
|
Lock l;
|
|
Ref r;
|
|
Chan **fd;
|
|
int nfd; /* number allocated */
|
|
int maxfd; /* highest fd in use */
|
|
int exceed; /* debugging */
|
|
};
|
|
|
|
enum
|
|
{
|
|
DELTAFD = 20 /* incremental increase in Fgrp.fd's */
|
|
};
|
|
|
|
struct Waitq
|
|
{
|
|
Waitmsg w;
|
|
Waitq* next;
|
|
};
|
|
|
|
/*
|
|
* fasttick timer interrupts
|
|
*/
|
|
typedef enum TimerMode {
|
|
Trelative, /* timer programmed in ns from now */
|
|
Tperiodic, /* periodic timer, period in ns */
|
|
} TimerMode;
|
|
|
|
struct Timer
|
|
{
|
|
/* Internal */
|
|
Lock l;
|
|
Timers* tt; /* Timers queue this timer runs on */
|
|
int64_t twhen; /* ns represented in fastticks */
|
|
Timer* tnext;
|
|
|
|
/* Public interface */
|
|
int64_t tns; /* meaning defined by mode */
|
|
void (*tf)(Ureg*, Timer*);
|
|
void* ta;
|
|
TimerMode tmode;
|
|
};
|
|
|
|
enum
|
|
{
|
|
RFNAMEG = (1<<0),
|
|
RFENVG = (1<<1),
|
|
RFFDG = (1<<2),
|
|
RFNOTEG = (1<<3),
|
|
RFPROC = (1<<4),
|
|
RFMEM = (1<<5),
|
|
RFNOWAIT = (1<<6),
|
|
RFCNAMEG = (1<<10),
|
|
RFCENVG = (1<<11),
|
|
RFCFDG = (1<<12),
|
|
RFREND = (1<<13),
|
|
RFNOMNT = (1<<14),
|
|
};
|
|
|
|
/*
|
|
* process memory segments - NSEG always last !
|
|
*/
|
|
enum
|
|
{
|
|
SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, SEG3, SEG4, NSEG
|
|
};
|
|
|
|
typedef enum ProcState
|
|
{
|
|
Dead = 0, /* Process states */
|
|
Moribund,
|
|
Broken,
|
|
Ready,
|
|
Scheding,
|
|
Running,
|
|
Queueing,
|
|
QueueingR,
|
|
QueueingW,
|
|
Wakeme,
|
|
Stopped,
|
|
Rendezvous,
|
|
Waitrelease,
|
|
} ProcState;
|
|
|
|
enum
|
|
{
|
|
Proc_stopme = 1, /* devproc requests */
|
|
Proc_exitme,
|
|
Proc_traceme,
|
|
Proc_exitbig,
|
|
Proc_tracesyscall,
|
|
|
|
TUser = 0, /* Proc.time */
|
|
TSys,
|
|
TReal,
|
|
TCUser,
|
|
TCSys,
|
|
TCReal,
|
|
|
|
NERR = 64,
|
|
NNOTE = 5,
|
|
|
|
Npriq = 20, /* number of scheduler priority levels */
|
|
PriNormal = 10, /* base priority for normal processes */
|
|
PriKproc = 13, /* base priority for kernel processes */
|
|
PriRoot = 13, /* base priority for root processes */
|
|
|
|
};
|
|
|
|
struct Schedq
|
|
{
|
|
Lock l;
|
|
Proc* head;
|
|
Proc* tail;
|
|
int n;
|
|
};
|
|
|
|
typedef union ScRet ScRet;
|
|
union ScRet {
|
|
int i;
|
|
long l;
|
|
uintptr_t p;
|
|
usize u;
|
|
void* v;
|
|
int64_t vl;
|
|
};
|
|
|
|
typedef struct ProcWakeup
|
|
{
|
|
int count; /* reduced when moved to ringing or cleared */
|
|
Syscalls blockingsc; /* set to cursyscall on sleep() and sysrendevouz
|
|
* reset by syscall
|
|
*/
|
|
unsigned long fell_asleep; /* debug: last time we went to sleep */
|
|
unsigned long awakened; /* debug: last time we stopped sleeping */
|
|
AwakeAlarm* elapsed;
|
|
unsigned long last; /* freed on pexit/noted */
|
|
} ProcWakeup;
|
|
|
|
struct Proc
|
|
{
|
|
Label sched; /* known to l.s */
|
|
char* kstack; /* known to l.s */
|
|
Ureg* dbgreg; /* known to l.s User registers for devproc */
|
|
Mach* mach; /* machine running this proc */
|
|
char* text;
|
|
char* user;
|
|
char** args;
|
|
int nargs; /* number of bytes of args */
|
|
Proc* rnext; /* next process in run queue */
|
|
Proc* qnext; /* next process on queue for a QLock */
|
|
QLock* qlock; /* addr of qlock being queued for DEBUG */
|
|
ProcState state;
|
|
char* psstate; /* What /proc/#/status reports */
|
|
ProcSegment* seg[NSEG];
|
|
RWlock seglock; /* wlocked whenever seg[] changes */
|
|
int pid;
|
|
int index; /* index (slot) in proc array */
|
|
int ref; /* indirect reference */
|
|
int noteid; /* Equivalent of note group */
|
|
Proc* pidhash; /* next proc in pid hash */
|
|
|
|
Lock exl; /* Lock count and waitq */
|
|
Waitq* waitq; /* Exited processes wait children */
|
|
int nchild; /* Number of living children */
|
|
int nwait; /* Number of uncollected wait records */
|
|
QLock qwaitr;
|
|
Rendez waitr; /* Place to hang out in wait */
|
|
Proc* parent;
|
|
|
|
Pgrp* pgrp; /* Process group for namespace */
|
|
Egrp* egrp; /* Environment group */
|
|
Fgrp* fgrp; /* File descriptor group */
|
|
Rgrp* rgrp; /* Rendez group */
|
|
|
|
Fgrp* closingfgrp; /* used during teardown */
|
|
|
|
int parentpid;
|
|
uint64_t time[6]; /* User, Sys, Real; child U, S, R */
|
|
|
|
uint64_t kentry; /* Kernel entry time stamp (for profiling) */
|
|
/*
|
|
* pcycles: cycles spent in this process (updated on procsave/restore)
|
|
* when this is the current proc and we're in the kernel
|
|
* (procrestores outnumber procsaves by one)
|
|
* the number of cycles spent in the proc is pcycles + cycles()
|
|
* when this is not the current process or we're in user mode
|
|
* (procrestores and procsaves balance), it is pcycles.
|
|
*/
|
|
int64_t pcycles;
|
|
Profbuf* prof;
|
|
|
|
int inkernel; /* either on syscall or fault */
|
|
int fpstate;
|
|
Syscalls cursyscall; /* zero on fault */
|
|
|
|
int32_t blockingfd; /* fd currenly read/written */
|
|
|
|
QLock debug; /* to access debugging elements of User */
|
|
Proc* pdbg; /* the debugging process */
|
|
uint32_t procmode; /* proc device file mode */
|
|
uint32_t privatemem; /* proc does not let anyone read mem */
|
|
int hang; /* hang at next exec for debug */
|
|
int procctl; /* Control for /proc debugging */
|
|
uintptr_t pc; /* DEBUG only */
|
|
|
|
Lock rlock; /* sync sleep/wakeup with postnote */
|
|
Rendez* r; /* rendezvous point slept on */
|
|
Rendez sleep; /* place for syssleep/debug */
|
|
int notepending; /* note issued but not acted on */
|
|
int notedeferred; /* note not to be acted on immediately */
|
|
int kp; /* true if a kernel process */
|
|
uint32_t alarm; /* Time of call */
|
|
Proc* palarm; /* Next alarm time */
|
|
|
|
int nwakeups; /* number of allocated AwakeAlarms */
|
|
ProcWakeup wakeups[2]; /* sysawake support */
|
|
|
|
int newtlb; /* Pager has changed my pte's, I must flush */
|
|
int noswap; /* process is not swappable */
|
|
|
|
uintptr_t rendtag; /* Tag for rendezvous */
|
|
uintptr_t rendval; /* Value for rendezvous */
|
|
Proc* rendhash; /* Hash list for tag values */
|
|
|
|
Timer; /* For tsleep and real-time */
|
|
Rendez* trend;
|
|
int (*tfn)(void*);
|
|
void (*kpfun)(void*);
|
|
void* kparg;
|
|
|
|
int scallnr; /* system call number */
|
|
uint8_t arg[MAXSYSARG*sizeof(void*)]; /* system call arguments */
|
|
int nerrlab;
|
|
Label errlab[NERR];
|
|
long syscallerr; /* (negative) error code to return from syscalls */
|
|
char* syserrstr; /* last error from a system call, errbuf0 or 1 */
|
|
char* errstr; /* reason we're unwinding the error stack, errbuf1 or 0 */
|
|
char errbuf0[ERRMAX];
|
|
char errbuf1[ERRMAX];
|
|
char genbuf[128]; /* buffer used e.g. for last name element from namec */
|
|
Chan* slash;
|
|
Chan* dot;
|
|
|
|
Note note[NNOTE];
|
|
short nnote;
|
|
short notified; /* sysnoted is due */
|
|
Note lastnote;
|
|
void (*notify)(void*, char*);
|
|
|
|
Lock* lockwait;
|
|
Lock* lastlock; /* debugging */
|
|
Lock* lastilock; /* debugging */
|
|
|
|
Mach* wired;
|
|
Mach* mp; /* machine this process last ran on */
|
|
int nlocks; /* number of locks held by proc */
|
|
int lockdepth;
|
|
uint32_t delaysched;
|
|
uint32_t priority; /* priority level */
|
|
uint32_t basepri; /* base priority level */
|
|
int fixedpri; /* priority level does not change */
|
|
uint64_t cpu; /* cpu average */
|
|
uint64_t lastupdate;
|
|
uint64_t readytime; /* time process came ready */
|
|
uint64_t movetime; /* last time process switched processors */
|
|
int preempted; /* true if this process hasn't finished the interrupt
|
|
* that last preempted it
|
|
*/
|
|
int trace; /* process being traced? */
|
|
|
|
uintptr_t qpc; /* pc calling last blocking qlock */
|
|
QLock *eql; /* interruptable eqlock */
|
|
|
|
int setargs;
|
|
|
|
void* ureg; /* User registers for notes */
|
|
|
|
Queue* syscallq;
|
|
|
|
FPsave fpsave;
|
|
PMMU;
|
|
PNOTIFY;
|
|
};
|
|
|
|
struct Procalloc
|
|
{
|
|
Lock l;
|
|
Proc* ht[128];
|
|
Proc* arena;
|
|
Proc* free;
|
|
int nproc;
|
|
};
|
|
|
|
enum
|
|
{
|
|
PRINTSIZE = 256,
|
|
NUMSIZE = 12, /* size of formatted number */
|
|
MB = (1024*1024),
|
|
/* READSTR was 1000, which is way too small for usb's ctl file */
|
|
READSTR = 4000, /* temporary buffer size for device reads */
|
|
};
|
|
|
|
extern Pool* secrmem;
|
|
|
|
extern char* conffile;
|
|
extern int cpuserver;
|
|
extern char* eve;
|
|
extern char hostdomain[];
|
|
extern uint8_t initcode[];
|
|
extern int kbdbuttons;
|
|
extern Ref noteidalloc;
|
|
extern int nphysseg;
|
|
extern int nsyscall;
|
|
extern Procalloc procalloc;
|
|
extern RMap rmapram;
|
|
extern uint32_t qiomaxatomic;
|
|
extern char* statename[];
|
|
extern char* sysname;
|
|
extern Queue* serialoq;
|
|
|
|
enum
|
|
{
|
|
LRESPROF = 3,
|
|
};
|
|
|
|
/*
|
|
* action log
|
|
*/
|
|
struct Log {
|
|
Lock l;
|
|
int opens;
|
|
char* buf;
|
|
char *end;
|
|
char *rptr;
|
|
int len;
|
|
int nlog;
|
|
int minread;
|
|
|
|
int logmask; /* mask of things to debug */
|
|
|
|
QLock readq;
|
|
Rendez readr;
|
|
};
|
|
|
|
struct Logflag {
|
|
char* name;
|
|
int mask;
|
|
};
|
|
|
|
enum
|
|
{
|
|
NCMDFIELD = 128
|
|
};
|
|
|
|
struct Cmdbuf
|
|
{
|
|
char *buf;
|
|
char **f;
|
|
int nf;
|
|
};
|
|
|
|
struct Cmdtab
|
|
{
|
|
int index; /* used by client to switch on result */
|
|
char *cmd; /* command name */
|
|
int narg; /* expected #args; 0 ==> variadic */
|
|
};
|
|
|
|
/*
|
|
* routines to access UART hardware
|
|
*/
|
|
struct PhysUart
|
|
{
|
|
char* name;
|
|
Uart* (*pnp)(void);
|
|
void (*enable)(Uart*, int);
|
|
void (*disable)(Uart*);
|
|
void (*kick)(Uart*);
|
|
void (*dobreak)(Uart*, int);
|
|
int (*baud)(Uart*, int);
|
|
int (*bits)(Uart*, int);
|
|
int (*stop)(Uart*, int);
|
|
int (*parity)(Uart*, int);
|
|
void (*modemctl)(Uart*, int);
|
|
void (*rts)(Uart*, int);
|
|
void (*dtr)(Uart*, int);
|
|
long (*status)(Uart*, void*, long, long);
|
|
void (*fifo)(Uart*, int);
|
|
void (*power)(Uart*, int);
|
|
int (*getc)(Uart*); /* polling version for rdb */
|
|
void (*putc)(Uart*, int); /* polling version for iprint */
|
|
};
|
|
|
|
enum {
|
|
Stagesize= 2048
|
|
};
|
|
|
|
/*
|
|
* software UART
|
|
*/
|
|
struct Uart
|
|
{
|
|
void* regs; /* hardware stuff */
|
|
void* saveregs; /* place to put registers on power down */
|
|
char* name; /* internal name */
|
|
uint32_t freq; /* clock frequency */
|
|
int bits; /* bits per character */
|
|
int stop; /* stop bits */
|
|
int parity; /* even, odd or no parity */
|
|
int baud; /* baud rate */
|
|
PhysUart*phys;
|
|
int console; /* used as a serial console */
|
|
int special; /* internal kernel device */
|
|
Uart* next; /* list of allocated uarts */
|
|
|
|
QLock ql;
|
|
int type; /* ?? */
|
|
int dev;
|
|
int opens;
|
|
|
|
int enabled;
|
|
Uart *elist; /* next enabled interface */
|
|
|
|
int perr; /* parity errors */
|
|
int ferr; /* framing errors */
|
|
int oerr; /* rcvr overruns */
|
|
int berr; /* no input buffers */
|
|
int serr; /* input queue overflow */
|
|
|
|
/* buffers */
|
|
int (*putc)(Queue*, int);
|
|
Queue *iq;
|
|
Queue *oq;
|
|
|
|
Lock rlock;
|
|
uint8_t istage[Stagesize];
|
|
uint8_t *iw;
|
|
uint8_t *ir;
|
|
uint8_t *ie;
|
|
|
|
Lock tlock; /* transmit */
|
|
uint8_t ostage[Stagesize];
|
|
uint8_t *op;
|
|
uint8_t *oe;
|
|
int drain;
|
|
|
|
int modem; /* hardware flow control on */
|
|
int xonoff; /* software flow control on */
|
|
int blocked;
|
|
int cts, dsr, dcd; /* keep track of modem status */
|
|
int ctsbackoff;
|
|
int hup_dsr, hup_dcd; /* send hangup upstream? */
|
|
int dohup;
|
|
|
|
Rendez r;
|
|
};
|
|
|
|
extern Uart* consuart;
|
|
|
|
/*
|
|
* performance timers, all units in perfticks
|
|
*/
|
|
struct Perf
|
|
{
|
|
uint64_t intrts; /* time of last interrupt */
|
|
uint64_t inintr; /* time since last clock tick in interrupt handlers */
|
|
uint64_t avg_inintr; /* avg time per clock tick in interrupt handlers */
|
|
uint64_t inidle; /* time since last clock tick in idle loop */
|
|
uint64_t avg_inidle; /* avg time per clock tick in idle loop */
|
|
uint64_t last; /* value of perfticks() at last clock tick */
|
|
uint64_t period; /* perfticks() per clock tick */
|
|
};
|
|
|
|
struct Watchdog
|
|
{
|
|
void (*enable)(void); /* watchdog enable */
|
|
void (*disable)(void); /* watchdog disable */
|
|
void (*restart)(void); /* watchdog restart */
|
|
void (*stat)(char*, char*); /* watchdog statistics */
|
|
};
|
|
|
|
/* queue state bits, Qmsg, Qcoalesce, and Qkick can be set in qopen */
|
|
enum
|
|
{
|
|
/* Queue.state */
|
|
Qstarve = (1<<0), /* consumer starved */
|
|
Qmsg = (1<<1), /* message stream */
|
|
Qclosed = (1<<2), /* queue has been closed/hungup */
|
|
Qflow = (1<<3), /* producer flow controlled */
|
|
Qcoalesce = (1<<4), /* coalesce packets on read */
|
|
Qkick = (1<<5), /* always call the kick routine after qwrite */
|
|
};
|
|
|
|
#define DEVDOTDOT -1
|
|
|
|
#pragma varargck type "I" uint8_t*
|
|
#pragma varargck type "V" uint8_t*
|
|
#pragma varargck type "E" uint8_t*
|
|
#pragma varargck type "M" uint8_t*
|
|
|
|
#pragma varargck type "m" Mreg
|
|
#pragma varargck type "P" uintmem
|