/*
 * 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/>.
 */
void		_assert(char*);
void		accounttime(void);
void		addbootfile(char*, uint8_t*, uint32_t);
Timer*		addclock0link(void (*)(void), int);
int		addconsdev(Queue*, void (*fn)(char*,int), int, int);
int		addkbdq(Queue*, int);
void		adduser(char*, char*, int, char**);
void		addwatchdog(Watchdog*);
int		adec(int*);
short		adec16(short*);
Block*		adjustblock(Block*, int);
int		ainc(int*);
short		ainc16(short*);
void		alarmkproc(void*);
Block*		allocb(int);
Block*		allocbalign(int, int);
int		anyhigher(void);
int		anyready(void);
void		awake_tick(unsigned long tick);
void		awake_timer(void*);
void		awake_ringer(void*);
void		awake_gc_proc(Proc *p);
int		awake_should_wake_up(Proc *p);
void		awake_fell_asleep(Proc *p);
void		awake_awakened(Proc *p);
void		awake_gc_note(Proc *p);
Block*		bl2mem(uint8_t*, Block*, int);
int		blocklen(Block*);
void		bootlinks(void);
Bpool*		bpoolcreate(uint32_t, uint32_t, uintmem, uintmem, void* (*)(usize, int));
uintmem		bpoolalloc(Bpool*, usize);
void		bpoolfree(Bpool*, uintmem, usize);
void		bpoolallocrange(Bpool*, usize*, usize*);
void		bpoolinitfree(Bpool*, uintmem, uintmem);
void		bpooldump(Bpool*);
void		callwithureg(void (*)(Ureg*));
char*		chanpath(Chan*);
int		canlock(Lock*);
int		canqlock(QLock*);
int		canrlock(RWlock*);
Chan*		cclone(Chan*);
void		cclose(Chan*);
void		ccloseq(Chan*);
void		(*consdebug)(void);
void		(*screenputs)(char*, int);
void		chanfree(Chan*);
void		checkalarms(void);
void		checkb(Block*, char*);
void		checkflushmmu(void);
void		checkmmu(uintptr_t, uintmem);
void		closeegrp(Egrp*);
void		closefgrp(Fgrp*);
void		closepgrp(Pgrp*);
void		closergrp(Rgrp*);
void		cmderror(Cmdbuf*, char*) __attribute__ ((noreturn));
int		cmount(Chan**, Chan*, int, char*);
#define	commonerror()	(up->errstr)
#define	commonuser()	(up->user)
Block*		concatblock(Block*);
int		consactive(void);
Block*		copyblock(Block*, int);
void		cunmount(Chan*, Chan*);
uintptr_t		dbgpc(Proc*);
int		decref(Ref*);
int		decrypt(void*, void*, int);
void		delay(int);
void		delconsdevs(void);
int		deluser(char*);
Proc*		dequeueproc(Schedq*, Proc*);
Chan*		devattach(int, char*);
Block*		devbread(Chan*, long, int64_t);
long		devbwrite(Chan*, Block*, int64_t);
Dev*		devbyname(char*);
Chan*		devclone(Chan*);
int		devconfig(int, char *, DevConf *);
Chan*		devcreate(Chan*, char*, unsigned long, unsigned long);
void		devdir(Chan*, Qid, char*, int64_t, char*, long, Dir*);
long		devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen		devgen;
void		devinit(void);
Chan*		devopen(Chan*, unsigned long, Dirtab*, int, Devgen*);
void		devpermcheck(char*, int, int);
void		devpower(int);
long		devreadv(Chan*, IOchunk*, long, long, int64_t);
void		devremove(Chan*);
void		devreset(void);
void		devshutdown(void);
long		devstat(Chan*, uint8_t*, long, Dirtab*, int, Devgen*);
Dev*		devtabget(int, int);
void		devtabinit(void);
long		devtabread(Chan*, void*, long, int64_t);
void		devtabreset(void);
void		devtabshutdown(void);
long		devwritev(Chan*, IOchunk*, long, long, int64_t);
long		devwstat(Chan*, uint8_t*, long);
Walkqid*	devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
void		drawactive(int);
void		drawcmap(void);
void		dumpaproc(Proc*);
void		dumpregs(Ureg*);
void		dumpstack(void);
Fgrp*		dupfgrp(Fgrp*);
int		elf64ldseg(Chan *c, uintptr_t *entryp, Ldseg **rp, char *mach, uint32_t minpgsz);
int		emptystr(char*);
int		encrypt(void*, void*, int);
void		envcpy(Egrp*, Egrp*);
int		eqchanddq(Chan*, int, uint32_t, Qid, int);
void		eqlock(QLock *q);
int		eqqid(Qid, Qid);
void		error(char*) __attribute__ ((noreturn));
void		errorl(char*, long) __attribute__ ((noreturn));
void		errorf(char*, ...) __attribute__ ((noreturn));
void		exhausted(char*) __attribute__ ((noreturn));
void		exit(int) __attribute__ ((noreturn));
uint64_t		fastticks(uint64_t*);
uint64_t		fastticks2us(uint64_t);
uint64_t		fastticks2ns(uint64_t);
int		fault(uintptr_t, uintptr_t, int);
void		fdclose(int, int);
Chan*		fdtochan(int, unsigned long, int, int);
int		findmount(Chan**, Mhead**, int, uint32_t, Qid);
int		fixfault(ProcSegment*, uintptr_t, int, int);
void		fmtinit(void);
void		forceclosefgrp(void);
void		free(void*);
void		freeb(Block*);
void		freeblist(Block*);
int		freebroken(void);
void		getcolor(uint32_t, uint32_t*, uint32_t*, uint32_t*);
void		gotolabel(Label*) __attribute__ ((noreturn));
char*		getconfenv(void);
int		haswaitq(void*);
long		hostdomainwrite(char*, long);
long		hostownerwrite(char*, long);
void 		(*hwrandbuf)(void*, uint32_t);
void		hzsched(void);
Block*		iallocb(int);
void		ialloclimit(uint32_t);
void		iallocsummary(void);
void		ilock(Lock*);
void		iunlock(Lock*);
int		incref(Ref*);
int		ingroup(char*, char*);
void		initimage(void);
void		interrupted(void);
int		iprint(char*, ...);
void		isdir(Chan*);
int		iseve(void);
int		isevegroup(void);
int		islo(void);
#define	islocked(l)	((l)->key != 0)
int		ispages(void*);
int		isphysseg(char*);
int		ismapped(RMap*, uintmem, uintmem*);
int		kbdcr2nl(Queue*, int);
int		kbdgetmap(int, int*, int*, Rune*);
int		kbdputc(Queue*, int);
void		kbdputmap(uint16_t, uint16_t, Rune);
void		kickpager(void);
void		killbig(char*);
void		kproc(char*, void(*)(void*), void*);
void		kprocchild(Proc*, void (*)(void*), void*);
void		(*kproftimer)(uintptr_t);
void		ksetenv(char*, char*, int);
void		kstrcpy(char*, char*, int);
void		kstrdup(char**, char*);
int			labtrap(char*);
long		latin1(Rune*, int);
int		leadsgroup(char*, char*);
int		lock(Lock*);
void		locksetpc(Lock*, uintptr_t);
void		logopen(Log*);
void		logclose(Log*);
char*		logctl(Log*, int, char**, Logflag*);
void		logn(Log*, int, void*, int);
long		logread(Log*, void*, uint32_t, long);
void		log(Log*, int, char*, ...);
Cmdtab*		lookupcmd(Cmdbuf*, Cmdtab*, int);
#define		MS2NS(n) (((int64_t)(n))*1000000LL)
void		mallocinit(void);
int			malloclocked(void);
long		mallocreadsummary(Chan*, void*, long, long);
void		mallocsummary(void);
Block*		mem2bl(uint8_t*, int);
void		microdelay(int);
uint64_t		mk64fract(uint64_t, uint64_t);
void		mkqid(Qid*, int64_t, uint32_t, int);
void		mmuflush(void);
void		mmuput(uintptr_t, uintptr_t);
void		mmurelease(Proc*);
void		mmuswitch(Proc*);
Chan*		mntauth(Chan*, char*);
Chan*		mntattach(Chan *c, Chan *ac, char *spec, int flags);
usize		mntversion(Chan*, uint32_t, char*, usize);
void		mountfree(Mount*);
int		mregfmt(Fmt*);
#define		ms2tk(n) (((n)*HZ+500)/1000)
uint64_t		ms2fastticks(uint32_t);
void		mul64fract(uint64_t*, uint64_t, uint64_t);
void		muxclose(Mnt*);
Chan*		namec(char*, int, long, long);
void		nameerror(char*, char*);
Chan*		newchan(void);
int		newfd(Chan*);
Mhead*		newmhead(Chan*);
Mount*		newmount(Mhead*, Chan*, int, char*);
Path*		newpath(char*);
Pgrp*		newpgrp(void);
Rgrp*		newrgrp(void);
Proc*		newproc(void);
void		nexterror(void) __attribute__ ((noreturn));
void		noteallow(void);
void		notedefer(void);
int		nrand(int);
uint64_t		ns2fastticks(uint64_t);
int		okaddr(uintptr_t, long, int);
unsigned long	openmode(unsigned long);
#define ownlock(l) (l->lm == MACHP(m->machno))
Block*		packblock(Block*);
Block*		padblock(Block*, int);
void		pageinit(void);
void	pagereclaim(int, int);
void	pagewake(void);
void		panic(char*, ...) __attribute__ ((noreturn));
Cmdbuf*		parsecmd(char *a, int n);
void		pathclose(Path*);
uint64_t	perfticks(void);
void		peekAtExecFaults(uintptr_t);
void		pexit(char*, int) __attribute__ ((noreturn));
void		pgrpcpy(Pgrp*, Pgrp*);
void		pgrpnote(uint32_t, char*, long, int);
void		physdump(void);
void		physinit(uintmem);
void		physinitfree(uintmem, uintmem);
uintmem	physalloc(usize);
void		physdump(void);
int		psindex(int);
#define		poperror()		up->nerrlab--
int		postnote(Proc*, int, char*, int);
void		prockill(Proc*, int, char*);
int		pprint(char*, ...);
int		preempted(void);
void		prflush(void);
void		printinit(void);
void		psinit(unsigned int);
uint64_t	procalarm(uint64_t);
void		procctl(Proc*);
uint32_t	procdatasize(Proc*, int);
void		procdump(void);
int		procfdprint(Chan*, int, int, char*, int);
void		procs_flush_segment(ProcSegment*);
void		procpriority(Proc*, int, int);
void		procrestore(Proc*);
void		procsave(Proc*);
int		proc_interrupt_finalize(Proc *p);
Proc*		psincref(int);
void		psdecref(Proc*);
void		(*proctrace)(Proc*, int, int64_t, int64_t);
void		procwired(Proc*, int);
Pte*		ptealloc(void);
Pte*		ptecpy(Pte*);
void		pteflush(Pte*, int, int);
int		pullblock(Block**, int);
Block*		pullupblock(Block*, int);
Block*		pullupqueue(Queue*, int);
void		putmhead(Mhead*);
void		putstrn(char*, int);
int		pwait(Waitmsg*);
int		qaddlist(Queue*, Block*);
int		qblen(Queue*);
Block*		qbread(Queue*, int);
long		qbwrite(Queue*, Block*);
Queue*		qbypass(void (*)(void*, Block*), void*);
int		qcanread(Queue*);
void		qclose(Queue*);
int		qconsume(Queue*, void*, int);
Block*		qcopy(Queue*, int, uint32_t);
int		qdiscard(Queue*, int);
void		qflush(Queue*);
void		qfree(Queue*);
int		qfull(Queue*);
Block*		qget(Queue*);
void		qhangup(Queue*, char*);
int		qisclosed(Queue*);
int		qiwrite(Queue*, void*, int);
int		qlen(Queue*);
void		qlock(QLock*);
Queue*		qopen(int, int, void (*)(void*), void*);
int		qpass(Queue*, Block*);
int		qpassnolim(Queue*, Block*);
int		qproduce(Queue*, void*, int);
void		qputback(Queue*, Block*);
long		qread(Queue*, void*, int);
Block*		qremove(Queue*);
void		qreopen(Queue*);
void		qsetbypass(Queue*, void (*)(void*, Block*), void*);
void		qsetlimit(Queue*, int);
void		qsleep(Queue*);
int		qstate(Queue *q);
void		qunlock(QLock*);
int		qwindow(Queue*);
int		qwrite(Queue*, void*, int);
void		qnoblock(Queue*, int);
int		rand(void);
void		randominit(void);
uint32_t		randomread(void*, uint32_t);
void		rdb(void);
long		readblist(Block*, unsigned char*, long, unsigned int);
int		readnum(uint32_t, char*, uint32_t, uint32_t, int);
long		readstr(long, char*, long, char*);
void		ready(Proc*);
void		rebootcmd(int, char**);
void		reboot(void*, void*, long);
void		renameuser(char*, char*);
void		resched(char*);
void		resrcwait(char*, char*);
int		return0(void*);
void		rlock(RWlock*);

uintptr_t	mapalloc(RMap*, uintptr_t, int, int);
void		mapfree(RMap*, uintptr_t, uintptr_t);
void		mapprint(RMap*);
int		mapfirst(RMap *r, uintptr_t start, uintptr_t *addr, uintptr_t *size);
uintptr_t	mapsize(RMap *r);
uintptr_t	maptop(RMap *r);

long		rtctime(void);
void		runlock(RWlock*);
Proc*		runproc(void);
void		sched(void);
void		scheddump(void);
void		schedinit(void);
void*		secalloc(uint32_t);
void		secfree(void*);
long		seconds(void);
char*	seprintbpoolstats(Bpool*, char*, char*);
char*	seprintphysstats(char*, char*);
int		setcolor(uint32_t, uint32_t, uint32_t, uint32_t);
void		setkernur(Ureg*, Proc*);
int		setlabel(Label*);
void		setregisters(Ureg*, char*, char*, int);
void		shrrenameuser(char *old, char *new);
char*		skipslash(char*);
void		sleep(Rendez*, int (*)(void*), void*);
void*		smalloc(uint32_t);
char*		srvname(Chan*);
void		srvrenameuser(char *old, char *new);
char*	syscallfmt(int syscall, Ureg* ureg);
char*	sysretfmt(int syscall, Ureg* ureg, ScRet* retv, uint64_t start, uint64_t stop);
void	dispatch_syscall(int syscall, Ureg* ureg, ScRet* ret);
char*	syscall_name(int syscall);
ScRet	default_syscall_ret(int syscall);
void		sysrforkchild(Proc*, Proc*);
#define	tickscmp(a, b)  (((int64_t)a)-((int64_t)b))
void		timeradd(Timer*);
void		timerdel(Timer*);
void		timersinit(void);
void		timerintr(Ureg*, void*);
void		timerset(Tval);
#define		tk2ms(x) ((x)*(1000/HZ))
#define		TK2MS(x) ((x)*(1000/HZ))
uint64_t		tod2fastticks(int64_t);
int64_t		todget(int64_t*);
void		todsetfreq(int64_t);
void		todinit(void);
void		todset(int64_t, int64_t, int);
void		tsleep(Rendez*, int (*)(void*), void*, int64_t);
Block*		trimblock(Block*, int, int);
int		uartctl(Uart*, char*);
int		uartgetc(void);
void		uartkick(void*);
void		uartmouse(char*, int (*)(Queue*, int), int);
void		uartsetmouseputc(char*, int (*)(Queue*, int));
void		uartputc(int);
void		uartputs(char*, int);
void		uartrecv(Uart*, char);
int		uartstageoutput(Uart*);
void		unbreak(Proc*);
int32_t		unionread(Chan *c, void *va, int32_t n);
void		unlock(Lock*);
void		userinit(void);
uintptr_t		userpc(Ureg*);
char*	usersread(void);
long		userswrite(void*, long);
long		userwrite(char*, long);
void*		validaddr(void*, long, int);
void		validname(char*, int);
char*		validnamedup(char*, int);
void		validstat(uint8_t*, usize);
void*		vmemchr(void*, int, int);
Proc*		wakeup(Rendez*);
int		walk(Chan**, char**, int, int, int*);
void		wlock(RWlock*);
void		wunlock(RWlock*);
void*		xalloc(uint32_t);
void*		xallocz(uint32_t, int);
void		xfree(void*);
void		xhole(uintptr_t, uintptr_t);
void		xinit(void);
int		xmerge(void*, void*);
void*		xspanalloc(uint32_t, int, uint32_t);
void		xsummary(void);
void		yield(void);
void		hnputv(void*, uint64_t);
void		hnputl(void*, uint32_t);
void		hnputs(void*, uint16_t);
uint64_t		nhgetv(void*);
uint32_t		nhgetl(void*);
uint16_t		nhgets(void*);
uint32_t		microseconds(void);

#pragma varargck 	argpos 	errorf 		1
#pragma varargck	argpos	iprint		1
#pragma varargck	argpos	panic		1
#pragma varargck	argpos	pprint		1

void*		xchgm(void*, void*);
int32_t		xchg32(int32_t*, int32_t);
uint32_t	xchg32u(uint32_t*, uint32_t);
#define ALIGNED(h, a)	((((uintptr_t)(h)) & (a-1)) == 0)

#define USED(...)
#define SET(...)

void*	qmalloc(uint32_t size);		// non zeroed
void*	sqmalloc(uint32_t size);	// safe, but non zeroed

void waitdebugger(void);
#define	INSPECT(x)	inspect((uintptr_t)x);
void inspect(uintptr_t);
