Files
xv6-custom-os/console.c
iDunnoDev c23d669858 Added draw menu, vars and additional functions needed for it
Added some functionality to the procdump to show the current console and parent pids of processes for debugging
Added var to clearconsole that enables the internal lock if one wasnt prelocked before hand
Fixed issue where race conditions would stop the title from drawing by drawing it to the buffer too
Fixed issue where the maze function was spamming the conswrite and cons lock by changing it to send an entire line instead of 1 char at a time
2022-12-23 00:48:57 +00:00

1136 lines
27 KiB
C

// Console input and output.
// Input is from the keyboard or serial port.
// Output is written to the screen and serial port.
#include "types.h"
#include "defs.h"
#include "param.h"
#include "traps.h"
#include "spinlock.h"
#include "sleeplock.h"
#include "fs.h"
#include "file.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
#define INPUT_BUF 128
// Proc title length + 3 for the console id + 2 for the left and right border + 2 for space between
#define MENUWIDTH 27
// Number of max consoles + 1 for bottom border and another 2 for a space between top and bottom
#define MENUHEIGHT (MAXVCONSOLES + 3);
static int currentmenuitem = 0;
static int menuactive = 0;
struct kbdbuffer
{
char buf[INPUT_BUF];
uint r; // Read index
uint w; // Write index
uint e; // Edit index
};
struct kbdbuffer inputBuffer;
struct kbdbuffer *input = 0;
struct vconsole
{
uint consoleindex;
struct spinlock lock;
struct proc *processowner;
ushort screenbuffer[SCRWIDTH * SCRHEIGHT];
struct kbdbuffer keybuffer;
int pos;
int active;
int inuse;
uint titlebgcol;
char proctitle[20];
int titlelocked;
char status[30];
};
struct vconsole consoles[MAXVCONSOLES];
struct vconsole *currentconsole = 0;
#define C(x) ((x) - '@') // Control-x
struct vconsole* getvalidprocessconsoleptr(void);
void clearconsole(ushort *bufferin);
void loadscreenbuffer(ushort *bufferin);
void savescreenbuffer(ushort *bufferin);
void clearscreen(int prelocked);
static void consputc(int);
static int panicked = 0;
static struct
{
struct spinlock lock;
int locking;
} cons;
// Lock for all consoles (to lock when doing switching/creating?)
static struct
{
struct spinlock lock;
int locking;
} vcons;
static int getcurrentactiveconsolecount(void)
{
int resultcount = 0;
for (int i = 0; i < MAXVCONSOLES; i++)
{
if (consoles[i].active)
{
resultcount++;
}
}
return resultcount;
}
static int getconsolemenuindex(struct vconsole* consolein)
{
int resultcount = 0;
for (int i = 0; i < MAXVCONSOLES; i++)
{
if (&consoles[i] == consolein && consoles[i].active)
{
break;
}
else
{
resultcount++;
}
}
return resultcount;
}
static int getmenuindexconsole(int menuindex)
{
int resultcount = 0;
int resultconsoleindex = 0;
for (int i = 0; i < MAXVCONSOLES; i++)
{
if (consoles[i].active)
{
if (resultcount == menuindex)
{
resultconsoleindex = consoles[i].consoleindex;
break;
}
else
{
resultcount++;
}
}
}
return resultconsoleindex;
}
int getconsoleindex(struct vconsole* consolein)
{
return consolein->consoleindex;
}
// Split the printint so we can just get the char out in draw title
// itoa is the function in the c standard library (?) so i reused the name
// since it does something similar
// Saves to the provided char array and returns the number of characters for looping
static int itoa(int xx, int base, int sign, char* buf)
{
static char digits[] = "0123456789abcdef";
int i;
uint x;
if (sign && (sign = xx < 0))
{
x = -xx;
}
else
{
x = xx;
}
i = 0;
do
{
buf[i++] = digits[x % base];
} while ((x /= base) != 0);
if (sign)
{
buf[i++] = '-';
}
return i;
}
static void printint(int xx, int base, int sign)
{
int i = 0;
char buf[16];
i = itoa(xx, base, sign, buf);
while (--i >= 0)
{
consputc(buf[i]);
}
}
// Print to the console. only understands %d, %x, %p, %s.
void cprintf(char *fmt, ...)
{
int i, c, locking;
uint *argp;
char *s;
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
locking = cons.locking;
if (locking)
{
//acquire(&cons.lock);
acquire(&inconsoleptr->lock);
}
if (fmt == 0)
{
panic("null fmt");
}
argp = (uint *)(void *)(&fmt + 1);
for (i = 0; (c = fmt[i] & 0xff) != 0; i++)
{
if (c != '%')
{
consputc(c);
continue;
}
c = fmt[++i] & 0xff;
if (c == 0)
{
break;
}
switch (c)
{
case 'd':
printint(*argp++, 10, 1);
break;
case 'x':
case 'p':
printint(*argp++, 16, 0);
break;
case 's':
if ((s = (char *)*argp++) == 0)
{
s = "(null)";
}
for (; *s; s++)
{
consputc(*s);
}
break;
case '%':
consputc('%');
break;
default:
// Print unknown % sequence to draw attention.
consputc('%');
consputc(c);
break;
}
}
if (locking)
{
//release(&cons.lock);
release(&inconsoleptr->lock);
}
}
void sprintf(char* strbuffer, char *fmt, ...)
{
int i, c, si;
uint *argp;
char *s;
char buf[16];
int x;
if (fmt == 0)
{
panic("null fmt");
}
si = 0;
argp = (uint *)(void *)(&fmt + 1);
for (i = 0; (c = fmt[i] & 0xff) != 0; i++)
{
if (c != '%')
{
strbuffer[si] = c;
si++;
continue;
}
c = fmt[++i] & 0xff;
if (c == 0)
{
break;
}
switch (c)
{
case 'd':
// Clear any existing buf data
memset(buf, 0, sizeof buf);
x = itoa(*argp++, 10, 1, buf);
while (--x >= 0)
{
strbuffer[si] = buf[x];
si++;
}
break;
case 'x':
case 'p':
// Clear any existing buf data
memset(buf, 0, sizeof buf);
x = itoa(*argp++, 16, 0, buf);
while (--x >= 0)
{
strbuffer[si] = buf[x];
si++;
}
break;
case 's':
if ((s = (char *)*argp++) == 0)
{
s = "(null)";
}
for (int sli = 0; sli < strlen(s); sli++)
{
strbuffer[si] = s[sli];
si++;
}
break;
case '%':
strbuffer[i] = '%';
si++;
break;
default:
// Print unknown % sequence to draw attention.
strbuffer[si] = '%';
si++;
strbuffer[si] = c;
si++;
break;
}
}
// Add string terminator to the end
strbuffer[si] = '\0';
}
void panic(char *s)
{
int i;
uint pcs[10];
cli();
cons.locking = 0;
// use lapiccpunum so that we can call panic from mycpu()
cprintf("lapicid %d: panic: ", lapicid());
cprintf(s);
cprintf("\n");
getcallerpcs(&s, pcs);
for (i = 0; i < 10; i++)
{
cprintf(" %p", pcs[i]);
}
panicked = 1; // freeze other CPU
for (;;)
{
;
}
}
// function that checks and returns a valid vconsole pointer, since i was repeating the same checks i moved it
// into its own function to keep things looking clean
struct vconsole* getvalidprocessconsoleptr(void)
{
struct vconsole* inconsoleptr = 0;
// Check if a process has actually been created otherwise use the base console
if (myproc() == 0x0)
{
inconsoleptr = currentconsole;
if (inconsoleptr == 0)
{
// fall back to the base console if the process and currentconsole has no console assigned for some reason
inconsoleptr = &consoles[0];
}
}
else
{
inconsoleptr = myproc()->consoleptr;
if (inconsoleptr == 0)
{
// fall back to the console set in currentconsole
inconsoleptr = currentconsole;
if (inconsoleptr == 0)
{
// fall back to the base console if the process and currentconsole has no console assigned for some reason
inconsoleptr = &consoles[0];
}
}
}
return inconsoleptr;
}
#define BACKSPACE 0x100
#define CRTPORT 0x3d4
#define TITLEOFF (SCRWIDTH * 1) // Size of the offset we need for the title bar
static ushort *crt = (ushort *)P2V(0xb8000); // CGA memory
static void drawmenu(void)
{
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
int rows = getcurrentactiveconsolecount() + 3;
int pos = TITLEOFF;
uint c = 0;
char menulines[MAXVCONSOLES][24];
for (int i = 0; i < MAXVCONSOLES; i++)
{
if (consoles[i].active)
{
memset(menulines[i], 0, sizeof(menulines[i][0]) * sizeof(menulines[i]));
sprintf(menulines[i], "%d: %s", consoles[i].consoleindex, consoles[i].proctitle);
}
}
for (int y = 0; y < rows; y++)
{
pos = TITLEOFF + (y * SCRWIDTH);
for (int x = 0; x < MENUWIDTH; x++)
{
if (y == 0 || y == (rows - 2))
{
if (x == 0 || x == (MENUWIDTH - 1))
{
c = 0xB2 | inconsoleptr->titlebgcol;
}
else
{
c = 0x0720;
}
}
else if (y == (rows - 1))
{
c = 0xB2 | inconsoleptr->titlebgcol;
}
else
{
if (x == 0 || x == (MENUWIDTH - 1))
{
c = 0xB2 | inconsoleptr->titlebgcol;
}
else if (x == 1 || x == (MENUWIDTH - 2))
{
c = 0x0720;
}
else
{
c = menulines[y - 1][x - 2];
c = (c & 0xff);
if (currentmenuitem == (y - 1))
{
c = c | 0xCF00;
}
else
{
c = c | 0x0700;
}
}
}
crt[pos] = c;
pos++;
}
}
menuactive = 1;
}
static void navigatemenu(int dir)
{
int pos = 0;
int newindex = currentmenuitem + dir;
int totalactiveconsoles = getcurrentactiveconsolecount();
if (newindex < 0)
{
newindex = 0;
}
else if (newindex >= totalactiveconsoles)
{
newindex = totalactiveconsoles - 1;
}
if (newindex != currentmenuitem)
{
pos = TITLEOFF + ((currentmenuitem + 1) * SCRWIDTH);
for (int x = 2; x < MENUWIDTH - 2; x++)
{
crt[pos + x] = (crt[pos + x] & 0x00FF) | 0x0700;
}
pos = TITLEOFF + ((newindex + 1) * SCRWIDTH);
for (int x = 2; x < MENUWIDTH - 2; x++)
{
crt[pos + x] = crt[pos + x] | 0xCF00;
}
currentmenuitem = newindex;
}
}
static void closemenu(void)
{
loadscreenbuffer(currentconsole->screenbuffer);
int pos = currentconsole->pos;
outb(CRTPORT, 14);
outb(CRTPORT + 1, pos >> 8);
outb(CRTPORT, 15);
outb(CRTPORT + 1, pos);
menuactive = 0;
}
static void drawtitle(void)
{
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
int pos = 0;
char c = ' ';
char menutext[] = "(M)enu";
char consoletitletext[10]; // + (inconsoleptr->consoleindex + 1);
sprintf(consoletitletext, "Console %d", inconsoleptr->consoleindex);
for (pos = 0; pos < SCRWIDTH; pos++)
{
int offset = 0;
if (pos < 6) {
c = menutext[pos - offset];
}
else if (pos >= 10 && pos < 20)
{
offset = 10;
c = consoletitletext[pos - offset];
}
else if (pos >= 25 && pos < 45)
{
offset = 25;
c = inconsoleptr->proctitle[pos - offset];
}
else if (pos >= 50 && pos < 80)
{
offset = 50;
c = inconsoleptr->status[pos - offset];
}
else
{
c = ' ';
}
if (inconsoleptr->inuse)
{
crt[pos] = (c & 0xff) | inconsoleptr->titlebgcol;
}
inconsoleptr->screenbuffer[pos] = (c & 0xff) | inconsoleptr->titlebgcol;
}
}
static void cgaputc(int c)
{
int pos;
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
ushort *currentbuffer = inconsoleptr->screenbuffer;
if (inconsoleptr->inuse)
{
// Cursor position: col + 80*row.
outb(CRTPORT, 14);
pos = inb(CRTPORT + 1) << 8;
outb(CRTPORT, 15);
pos |= inb(CRTPORT + 1);
}
else
{
pos = inconsoleptr->pos;
}
if (c == '\n')
{
pos += SCRWIDTH - pos % SCRWIDTH;
}
else if (c == BACKSPACE)
{
if (pos > (TITLEOFF))
{
currentbuffer[pos] = 0; // Clear the character from the buffer
--pos;
}
}
else
{
// int posp = pos;
if (inconsoleptr->inuse)
{
crt[pos] = (c & 0xff) | 0x0700; // black on white
}
currentbuffer[pos] = (c & 0xff) | 0x0700; // black on white
pos++;
}
if (pos < TITLEOFF || pos > SCRHEIGHT * SCRWIDTH)
{
panic("pos under/overflow");
}
if ((pos / 80) >= 24)
{ // Scroll up.
memmove(currentbuffer + TITLEOFF, currentbuffer + (SCRWIDTH + TITLEOFF), sizeof(crt[0]) * (SCRHEIGHT - 1) * SCRWIDTH);
pos -= 80;
memset(currentbuffer + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos));
if (inconsoleptr->inuse)
{
int menuoffset = 0;
if (menuactive)
{
int menuitems = getcurrentactiveconsolecount() + 3;
for (int y = 0; y < menuitems; y++)
{
memmove(crt + menuoffset + TITLEOFF + MENUWIDTH, crt + menuoffset + (SCRWIDTH + TITLEOFF) + MENUWIDTH, sizeof(crt[0]) * (SCRWIDTH - MENUWIDTH));
menuoffset += SCRWIDTH;
}
}
memmove(crt + TITLEOFF + menuoffset, crt + (SCRWIDTH + TITLEOFF) + menuoffset, (sizeof(crt[0]) * (SCRHEIGHT - 1) * SCRWIDTH) - menuoffset);
memset(crt + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos));
}
}
inconsoleptr->pos = pos;
if (inconsoleptr->inuse)
{
outb(CRTPORT, 14);
outb(CRTPORT + 1, pos >> 8);
outb(CRTPORT, 15);
outb(CRTPORT + 1, pos);
crt[pos] = ' ' | 0x0700;
}
}
void consputc(int c)
{
if (panicked)
{
cli();
for (;;)
{
;
}
}
if (c == BACKSPACE)
{
uartputc('\b');
uartputc(' ');
uartputc('\b');
}
else
{
uartputc(c);
}
cgaputc(c);
}
int consoleget(void)
{
//struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
int c;
acquire(&cons.lock);
while ((c = kbdgetc()) <= 0)
{
if (c == 0)
{
c = kbdgetc();
}
}
release(&cons.lock);
return c;
}
void consoleintr(int (*getc)(void))
{
int c;
int doprocdump = 0;
int doconsoleswitch = 0;
int switchto = -1;
int doconsolehome = 0;
//struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
struct kbdbuffer* consolekbdbuffer = &currentconsole->keybuffer;
acquire(&cons.lock);
while ((c = getc()) >= 0)
{
switch (c)
{
case 27:
if (menuactive)
{
closemenu();
}
break;
// Up arrow (found in kbd.h)
case 0xE2:
if (menuactive)
{
navigatemenu(-1);
}
break;
// Down arrow (found in kbd.h)
case 0xE3:
if (menuactive)
{
navigatemenu(1);
}
break;
case C('P'): // Process listing.
// procdump() locks cons.lock indirectly; invoke later
doprocdump = 1;
break;
case C('U'): // Kill line.
while (consolekbdbuffer->e != consolekbdbuffer->w &&
consolekbdbuffer->buf[(consolekbdbuffer->e - 1) % INPUT_BUF] != '\n')
{
consolekbdbuffer->e--;
consputc(BACKSPACE);
}
break;
case C('H'):
case '\x7f': // Backspace
if (consolekbdbuffer->e != consolekbdbuffer->w)
{
consolekbdbuffer->e--;
consputc(BACKSPACE);
}
break;
case C('T'):
doconsoleswitch = 1;
break;
case C('K'):
doconsolehome = 1;
break;
case C('M'):
if (!menuactive)
{
drawmenu();
}
else
{
closemenu();
}
break;
// If enter is hit and the menu is active then we want to override the normal behaviour
case 10:
if (menuactive)
{
closemenu();
switchto = currentmenuitem;
doconsoleswitch = 1;
// The menu has been sorted we can break from the switch
break;
}
// if the menu was not active we want the enter to be handled in the default case
default:
if (!menuactive)
{
if (c != 0 && consolekbdbuffer->e - consolekbdbuffer->r < INPUT_BUF)
{
c = (c == '\r') ? '\n' : c;
consolekbdbuffer->buf[consolekbdbuffer->e++ % INPUT_BUF] = c;
consputc(c);
if (c == '\n' || c == C('D') || consolekbdbuffer->e == consolekbdbuffer->r + INPUT_BUF)
{
consolekbdbuffer->w = consolekbdbuffer->e;
wakeup(&(consolekbdbuffer->r));
}
}
}
break;
}
}
release(&cons.lock);
if (doprocdump && !menuactive)
{
procdump(); // now call procdump() wo. cons.lock held
}
if (doconsolehome)
{
if (currentconsole->consoleindex != 0)
{
switchtoconsole(getbaseconsoleptr());
}
}
if (doconsoleswitch)
{
struct vconsole* toconsole = 0;
acquire(&cons.lock);
if (switchto == -1)
{
for (int i = (currentconsole->consoleindex + 1); i < MAXVCONSOLES; i++)
{
if (consoles[i].active)
{
toconsole = &consoles[i];
break;
}
}
if (toconsole == 0)
{
toconsole = getbaseconsoleptr();
}
}
else
{
toconsole = &consoles[getmenuindexconsole(switchto)];
}
release(&cons.lock);
if (!toconsole->inuse)
{
switchtoconsole(toconsole);
}
}
}
int consoleread(struct inode *ip, char *dst, int n)
{
uint target;
int c;
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
struct kbdbuffer* consolekbdbuffer = &inconsoleptr->keybuffer;
iunlock(ip);
target = n;
//acquire(&cons.lock);
acquire(&inconsoleptr->lock);
while (n > 0)
{
while (consolekbdbuffer->r == consolekbdbuffer->w)
{
if (myproc()->killed)
{
release(&inconsoleptr->lock);
ilock(ip);
return -1;
}
sleep(&(consolekbdbuffer->r), &inconsoleptr->lock);
}
c = consolekbdbuffer->buf[consolekbdbuffer->r++ % INPUT_BUF];
if (c == C('D'))
{ // EOF
if (n < target)
{
// Save ^D for next time, to make sure
// caller gets a 0-byte result.
consolekbdbuffer->r--;
}
break;
}
*dst++ = c;
--n;
if (c == '\n')
{
break;
}
}
//release(&cons.lock);
release(&inconsoleptr->lock);
ilock(ip);
return target - n;
}
int consolewrite(struct inode *ip, char *buf, int n)
{
int i;
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
iunlock(ip);
//acquire(&cons.lock);
acquire(&inconsoleptr->lock);
for (i = 0; i < n; i++)
{
consputc(buf[i] & 0xff);
}
//release(&cons.lock);
release(&inconsoleptr->lock);
ilock(ip);
return n;
}
// Function to flood a buffer with A-Z characters looping (for testing initially)
void testfillbuffer(ushort *bufferin)
{
ushort firstchar = 65;
ushort lastchar = 90;
ushort currentchar = firstchar;
for (int i = 0; i < (SCRHEIGHT * SCRWIDTH); i++)
{
if (currentchar > lastchar)
{
currentchar = firstchar;
}
bufferin[i] = (currentchar & 0xff) | 0x0700;
currentchar++;
}
}
struct vconsole* getbaseconsoleptr(void)
{
return &consoles[0];
}
void clearconsole(ushort *bufferin)
{
// Flood the screen buffer with blank spaces
memset(bufferin, 0, sizeof(bufferin[0]) * SCRHEIGHT * SCRWIDTH);
}
void loadscreenbuffer(ushort *bufferin)
{
// Copy the memory from the console buffer to the crt buffer
memmove(crt, bufferin, sizeof(bufferin[0]) * SCRHEIGHT * SCRWIDTH);
}
void savescreenbuffer(ushort *bufferin)
{
// Copy the memory from the console buffer to the crt buffer
memmove(bufferin, crt, sizeof(crt[0]) * SCRHEIGHT * SCRWIDTH);
}
void clearscreen(int prelocked)
{
// Check if a process has actually been created otherwise use the base console
struct vconsole* inconsoleptr = getvalidprocessconsoleptr();
if (!prelocked)
{
acquire(&cons.lock);
}
int pos = TITLEOFF;
clearconsole(inconsoleptr->screenbuffer);
inconsoleptr->pos = pos;
if (inconsoleptr->inuse)
{
loadscreenbuffer(inconsoleptr->screenbuffer);
outb(CRTPORT, 14);
outb(CRTPORT + 1, pos >> 8);
outb(CRTPORT, 15);
outb(CRTPORT + 1, pos);
}
drawtitle();
if (!prelocked)
{
release(&cons.lock);
}
}
void consoleinit(void)
{
initlock(&cons.lock, "console");
initlock(&vcons.lock, "vconglobal");
for (int i = 0; i < MAXVCONSOLES; i++)
{
consoles[i].consoleindex = i;
consoles[i].processowner = 0;
consoles[i].pos = 0;
consoles[i].active = 0;
consoles[i].inuse = 0;
consoles[i].titlebgcol = 0x4F00;
char lockname[8];
sprintf(lockname, "vconsole%d", i);
initlock(&consoles[i].lock, lockname);
}
// Initialise pointer to point to our console input buffer
currentconsole = &consoles[0];
currentconsole->active = 1;
currentconsole->inuse = 1;
input = &currentconsole->keybuffer;
devsw[CONSOLE].write = consolewrite;
devsw[CONSOLE].read = consoleread;
cons.locking = 1;
clearscreen(0);
cprintf("Welcome! you are currently in the base console\n");
ioapicenable(IRQ_KBD, 0);
}
struct vconsole* newconsole(char* title, int bgpreset)
{
struct vconsole* result = 0;
acquire(&vcons.lock);
for (int i = 1; i < MAXVCONSOLES; i++)
{
if (!consoles[i].active)
{
consoles[i].processowner = myproc();
consoles[i].titlebgcol = bgpreset;
if (strlen(title) > 0)
{
safestrcpy(consoles[i].proctitle, title, sizeof(consoles[i].proctitle));
consoles[i].titlelocked = 1;
}
else
{
consoles[i].titlelocked = 0;
}
result = &consoles[i];
break;
}
}
release(&vcons.lock);
return result;
}
void releaseallconsoles(void)
{
for (int i = 0; i < MAXVCONSOLES; i++)
{
consoles[i].inuse = 0;
}
}
int switchtoconsole(struct vconsole* consoleptr)
{
int pos;
acquire(&vcons.lock);
releaseallconsoles();
currentconsole = consoleptr;
currentconsole->inuse = 1;
//input = &currentconsole->keybuffer;
// ioapicenable(IRQ_KBD, 0);
acquire(&cons.lock);
loadscreenbuffer(currentconsole->screenbuffer);
if (!currentconsole->active)
{
clearscreen(1);
cprintf("Welcome to Console: %d\n", currentconsole->consoleindex);
currentconsole->active = 1;
}
else
{
pos = currentconsole->pos;
outb(CRTPORT, 14);
outb(CRTPORT + 1, pos >> 8);
outb(CRTPORT, 15);
outb(CRTPORT + 1, pos);
}
//drawtitle();
menuactive = 0;
currentmenuitem = getconsolemenuindex(currentconsole);
release(&cons.lock);
release(&vcons.lock);
return 0;
}
int closeconsole(void)
{
struct vconsole* consoleptr = myproc()->consoleptr;
//cprintf("Console Owner PID: %d\n", consoleptr->processowner->pid);
acquire(&vcons.lock);
if (myproc() == consoleptr->processowner)
{
clearconsole(consoleptr->screenbuffer);
consoleptr->active = 0;
if (consoleptr->inuse)
{
consoleptr->inuse = 0;
release(&vcons.lock);
switchtoconsole(&consoles[0]);
return 1;
}
}
release(&vcons.lock);
return 0;
}
int getcurrentconsoleindex(void)
{
acquire(&vcons.lock);
for (int i = 0; i < MAXVCONSOLES; i++)
{
if (consoles[i].inuse)
{
release(&vcons.lock);
return consoles[i].consoleindex;
}
}
release(&vcons.lock);
return -1;
}
void setconsoleproctitle(struct vconsole* consoleptr, char* newtitle)
{
if (!consoleptr->titlelocked)
{
acquire(&consoleptr->lock);
//Clear the current buffer
memset(consoleptr->proctitle, 0, sizeof(consoleptr->proctitle[0]) * sizeof(consoleptr->proctitle));
//Copy the new title into the console title buffer
safestrcpy(consoleptr->proctitle, newtitle, sizeof(consoleptr->proctitle));
//Redraw the title since its been updated now
drawtitle();
release(&consoleptr->lock);
}
}