mirror of
https://github.com/prirun/p50em.git
synced 2026-04-27 12:48:54 +00:00
Compare commits
19 Commits
dos19rvec
...
spamxonkil
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6d01cd05c | ||
|
|
ea2edd89de | ||
|
|
3d71fd85f0 | ||
|
|
5d119bb2c5 | ||
|
|
aa8095217f | ||
|
|
89043d09a4 | ||
|
|
e61857e333 | ||
|
|
4771f09e1e | ||
|
|
6bf6e2ea48 | ||
|
|
edf7129651 | ||
|
|
543aa3f963 | ||
|
|
7d7504a02e | ||
|
|
43d2d863d7 | ||
|
|
80c1a57895 | ||
|
|
d566f42ea6 | ||
|
|
af1718f699 | ||
|
|
91bddd02c3 | ||
|
|
4def8fe397 | ||
|
|
43bbf3cd8f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
*.log
|
||||
*.swp
|
||||
tags
|
||||
cmraw
|
||||
cscope.*
|
||||
em
|
||||
emlink
|
||||
|
||||
@@ -22,6 +22,9 @@ the host processor having a large set of general-purpose registers.
|
||||
Coming soon, we swear! There is a unix man page included in this
|
||||
repository.
|
||||
|
||||
Github discussions are now enabled for this repository, and can be
|
||||
used to ask for help.
|
||||
|
||||
## Public Systems
|
||||
|
||||
There are a set of emulators available for public use. These may be
|
||||
|
||||
54
devamlc.h
54
devamlc.h
@@ -262,6 +262,7 @@ int devamlc (int class, int func, int device) {
|
||||
unsigned short ctinterrupt; /* 1 bit per line */
|
||||
unsigned short dss; /* 1 bit per line */
|
||||
unsigned short connected; /* 1 bit per line */
|
||||
unsigned short dolineclear; /* 1 bit per line */
|
||||
unsigned short serial; /* true if any CT_SERIAL lines */
|
||||
unsigned short dsstime; /* countdown to dss poll */
|
||||
short fd[16]; /* Unix fd, 1 per line */
|
||||
@@ -329,6 +330,7 @@ int devamlc (int class, int func, int device) {
|
||||
for (dx=0; dx<MAXBOARDS; dx++) {
|
||||
dc[dx].deviceid = 0;
|
||||
dc[dx].connected = 0;
|
||||
dc[dx].dolineclear = 0;
|
||||
dc[dx].serial = 0;
|
||||
for (lx = 0; lx < 16; lx++) {
|
||||
dc[dx].fd[lx] = -1;
|
||||
@@ -885,6 +887,7 @@ int devamlc (int class, int func, int device) {
|
||||
close(dc[i].fd[lx]);
|
||||
dc[i].dss |= BITMASK16(lx+1);
|
||||
dc[i].connected |= BITMASK16(lx+1);
|
||||
dc[i].dolineclear |= BITMASK16(lx+1);
|
||||
dc[i].fd[lx] = fd;
|
||||
dc[i].tstate[lx] = TS_DATA;
|
||||
//printf("em: AMLC connection, fd=%d, device='%o, line=%d\n", fd, dc[i].deviceid, lx);
|
||||
@@ -911,10 +914,12 @@ int devamlc (int class, int func, int device) {
|
||||
optval = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval)) == -1)
|
||||
perror("unable to set TCP_NODELAY");
|
||||
#ifndef __APPLE__
|
||||
/* Set 600 second keepalive idle time for this socket */
|
||||
optval = 600;
|
||||
if (setsockopt(fd, 6 /* TCP */, TCP_KEEPIDLE, &optval, sizeof(optval)) == -1)
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(optval)) == -1)
|
||||
perror("unable to set TCP_KEEPIDLE");
|
||||
#endif
|
||||
/* ... and turn on keepalive */
|
||||
optval = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1)
|
||||
@@ -1138,6 +1143,53 @@ dorecv:
|
||||
if (dc[dx].deviceid == 0 || dc[dx].connected == 0 || dc[dx].eor)
|
||||
continue;
|
||||
|
||||
/* Inject xon / kill if dolineclear is true */
|
||||
|
||||
if (dolinecleararg)
|
||||
for (lx = 0; lx < 16; lx++)
|
||||
if (dc[dx].dolineclear & BITMASK16(lx+1))
|
||||
{
|
||||
unsigned char ch;
|
||||
unsigned short utemp;
|
||||
int dmcpair, lcount;
|
||||
ea_t dmcea, dmcbufbegea, dmcbufendea;
|
||||
unsigned short dmcnw;
|
||||
|
||||
if (dc[dx].bufnum)
|
||||
dmcea = dc[dx].dmcchan + 2;
|
||||
else
|
||||
dmcea = dc[dx].dmcchan;
|
||||
dmcpair = get32io(dmcea);
|
||||
dmcbufbegea = dmcpair>>16;
|
||||
dmcbufendea = dmcpair & 0xffff;
|
||||
dmcnw = dmcbufendea - dmcbufbegea + 1;
|
||||
|
||||
if (dmcnw < 2)
|
||||
continue;
|
||||
|
||||
utemp = lx<<12 | 0x0200 | 0221; /* dc1/xon */
|
||||
put16io(utemp, dmcbufbegea);
|
||||
dmcbufbegea = INCVA(dmcbufbegea, 1);
|
||||
|
||||
ch = (unsigned char)get16(MAKEVA(014, 0705));
|
||||
utemp = lx<<12 | 0x0200 | ch; /* kill */
|
||||
put16io(utemp, dmcbufbegea);
|
||||
dmcbufbegea = INCVA(dmcbufbegea, 1);
|
||||
|
||||
dc[dx].recvlx = lx;
|
||||
if (dmcbufbegea-1 > dmcbufendea)
|
||||
fatal("AMLC tumble table overflowed?");
|
||||
put16io(dmcbufbegea, dmcea);
|
||||
if (dmcbufbegea > dmcbufendea) { /* end of range has occurred */
|
||||
dc[dx].bufnum = 1-dc[dx].bufnum;
|
||||
dc[dx].eor = 1;
|
||||
neweor = 1;
|
||||
anyeor = 1;
|
||||
}
|
||||
|
||||
dc[dx].dolineclear &= ~BITMASK16(lx+1);
|
||||
}
|
||||
|
||||
/* select to see which lines have data to be read */
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
|
||||
33
em.1
33
em.1
@@ -2,7 +2,7 @@
|
||||
.\" em.1, Boone, 03/13/20
|
||||
.\" Man page for Jim Wilcoxson's Prime 50-Series emulator
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.TH em 1 "2020-03-14" "Jim Wilcoxson" "50-Series Emulator"
|
||||
.TH em 1 "2020-06-23" "Jim Wilcoxson" "50-Series Emulator"
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.SH NAME
|
||||
em \- Emulator for Prime 50-Series systems
|
||||
@@ -35,6 +35,8 @@ a tape controller, 4 drives, using the .TAP format
|
||||
.IP \(bu
|
||||
a PNC controller emulating RingNet over TCP/IP
|
||||
.IP \(bu
|
||||
two sync serial controllers supporting up to 8 lines
|
||||
.IP \(bu
|
||||
a bypass for Primos system serial number checks
|
||||
.IP \(bu
|
||||
Unix utilities to read/write physical tapes & Magsav tapes
|
||||
@@ -143,6 +145,15 @@ on the host. Multiple trace types may be listed, separated by
|
||||
spaces. Tracing may be initially turned off by including the
|
||||
.I off
|
||||
trace type.
|
||||
.PP
|
||||
\fB-dolineclear\fR
|
||||
.IP
|
||||
Inject an XON (DC1, 0221) character and a line kill character into the
|
||||
input buffers each time an AMLC line receives an incoming connection.
|
||||
The system's configured line kill character is fetched from the
|
||||
DEFKIL field of FIGCOM, at address 14(0)/705. This behavior helps
|
||||
counteract lines which have been blocked by internet vulnerability
|
||||
scanners injecting non-telnet data streams.
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.SH FILES
|
||||
.TP
|
||||
@@ -163,6 +174,18 @@ Example:
|
||||
8 192.168.10.4:9000 # Outbound socket connection e.g. for spooler
|
||||
.EE
|
||||
.TP
|
||||
smlc.cfg
|
||||
Used to associate outbound sync serial (MDLC or HSSMLC) lines with destination
|
||||
IP addresses and port numbers, or to associate inbound sync serial lines
|
||||
with port numbers. An outbound line corresponds to an RJE site defined as a
|
||||
SLAVE site, and an inbound line corresponds to an RJE site defined as a MASTER
|
||||
site. Optional. Comments work the same as amlc.cfg. Example:
|
||||
|
||||
.EX
|
||||
0 10.1.1.3:2554 # Connect to TCP port 2554 of host 10.1.1.3 for outbound line 0
|
||||
1 9951 # Listen on TCP port 9951 for inbound line 1
|
||||
.EE
|
||||
.TP
|
||||
console.log
|
||||
All console output is also written to this file. It is overwritten
|
||||
at each invocation. Created by
|
||||
@@ -274,9 +297,12 @@ off|Start with tracing disabled
|
||||
all|Everything
|
||||
flush|Flush trace file after each write
|
||||
tlb|STLB and IOTLB changes
|
||||
smlc|MDLC/HSSMLC device I/O
|
||||
OWNERL|Execution of this PCB
|
||||
instruction count|Begin after specified number of instructions
|
||||
#instruction count|Begin after specified number of instructions
|
||||
|(the leading # is literal)
|
||||
octal segno|Execution in the given segment number
|
||||
|(may interact poorly with "off")
|
||||
process number|Execution of this user number
|
||||
.TE
|
||||
.\" ---------------------------------------------------------------------------
|
||||
@@ -360,7 +386,8 @@ CMD,1/3/5+1,Cartridge Module 32/64/96 MB
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.SH AUTHOR
|
||||
.PP
|
||||
This emulator was written by Jim Wilcoxson. Man page by Dennis Boone.
|
||||
This emulator was written by Jim Wilcoxson. MDLC/HSSMLC support by
|
||||
Kevin Jordan. Man page by Dennis Boone.
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.SH SEE ALSO
|
||||
This project is hosted at
|
||||
|
||||
58
em.c
58
em.c
@@ -1,5 +1,5 @@
|
||||
/* Pr1me Computer emulator, Jim Wilcoxson (prirun@gmail.com), April 4, 2005
|
||||
Copyright (C) 2005-2019, Jim Wilcoxson. All Rights Reserved.
|
||||
Copyright (C) 2005-2021, Jim Wilcoxson. All Rights Reserved.
|
||||
|
||||
Emulates a Prime Computer system by:
|
||||
- booting from a Prime disk image (normal usage)
|
||||
@@ -287,6 +287,7 @@ static void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int
|
||||
T_PX Process exchange
|
||||
T_LM License manager
|
||||
T_TLB STLB and IOTLB changes
|
||||
T_SMLC SMLC device I/O
|
||||
*/
|
||||
|
||||
#define T_EAR 0x00000001
|
||||
@@ -309,6 +310,7 @@ static void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int
|
||||
#define T_GET 0x00020000
|
||||
#define T_EAS 0x00040000
|
||||
#define T_TLB 0x00080000
|
||||
#define T_SMLC 0x00100000
|
||||
|
||||
#define BITMASK16(b) (0x8000 >> ((b)-1))
|
||||
#define BITMASK32(b) ((unsigned int)(0x80000000) >> ((b)-1))
|
||||
@@ -656,6 +658,7 @@ static unsigned short *physmem = NULL; /* system's physical memory */
|
||||
|
||||
//static ea_t tnoua_ea=0, tnou_ea=0, tsrc_ea=0;
|
||||
static int domemdump; /* -memdump arg */
|
||||
static int dolinecleararg; /* -dolineclear arg */
|
||||
|
||||
static int tport; /* -tport option (incoming terminals) */
|
||||
static int nport; /* -nport option (PNC/Ringnet) */
|
||||
@@ -1689,6 +1692,8 @@ static int devpoll[64] = {0};
|
||||
'35 = devamlc: 4th AMLC (16 lines)
|
||||
'45 = devdisk: 7th disk controller (8 drives)
|
||||
'46 = devdisk: 8th disk controller (8 drives)
|
||||
'50 = devsmlc: 1st HSSMLC/MDLC (4 lines)
|
||||
'51 = devsmlc: 2nd HSSMLC/MDLC (4 lines)
|
||||
'52 = devamlc: 3rd AMLC (16 lines)
|
||||
'53 = devamlc: 2nd AMLC (16 lines)
|
||||
'54 = devamlc: 1st AMLC (16 lines)
|
||||
@@ -1700,7 +1705,7 @@ static int (*devmap[64])(int, int, int) = {
|
||||
/* '2x */ devcp,devnone,devdisk,devdisk,devdisk,devdisk,devdisk,devdisk,
|
||||
/* '3x */ devnone,devnone,devamlc,devnone,devnone,devamlc,devnone,devnone,
|
||||
/* '4x */ devnone,devnone,devnone,devnone,devnone,devdisk,devdisk,devnone,
|
||||
/* '5x */ devnone,devnone,devamlc,devamlc,devamlc,devnone,devnone,devnone,
|
||||
/* '5x */ devsmlc,devsmlc,devamlc,devamlc,devamlc,devnone,devnone,devnone,
|
||||
/* '6x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone,
|
||||
/* '7x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone};
|
||||
|
||||
@@ -1714,6 +1719,7 @@ static int (*devmap[64])(int, int, int) = {
|
||||
'20 = devcp: clock / VCP / SOC
|
||||
'26 = devdisk: 1st disk controller (8 drives)
|
||||
'27 = devdisk: 2nd disk controller (8 drives)
|
||||
'50 = devsmlc: 1st HSSMLC/MDLC (4 lines)
|
||||
'54 = 1st amlc (terminal) controller (16 lines)
|
||||
'53 = devamlc: 2nd AMLC (16 lines)
|
||||
*/
|
||||
@@ -1724,7 +1730,7 @@ static int (*devmap[64])(int, int, int) = {
|
||||
/* '2x */ devcp,devnone,devnone,devnone,devnone,devnone,devdisk,devdisk,
|
||||
/* '3x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone,
|
||||
/* '4x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone,
|
||||
/* '5x */ devnone,devnone,devnone,devamlc,devamlc,devnone,devnone,devnone,
|
||||
/* '5x */ devsmlc,devnone,devnone,devamlc,devamlc,devnone,devnone,devnone,
|
||||
/* '6x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone,
|
||||
/* '7x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone};
|
||||
#endif
|
||||
@@ -4363,7 +4369,7 @@ int main (int argc, char **argv) {
|
||||
#define XRBRACE 0375
|
||||
|
||||
printf("[Prime Emulator ver %s %s]\n", REV, __DATE__);
|
||||
printf("[Copyright (C) 2005-2019 Jim Wilcoxson prirun@gmail.com]\n");
|
||||
printf("[Copyright (C) 2005-2021 Jim Wilcoxson prirun@gmail.com]\n");
|
||||
if (argc > 1 && (strcmp(argv[1],"--version") == 0)) {
|
||||
exit(0);
|
||||
}
|
||||
@@ -4446,6 +4452,7 @@ int main (int argc, char **argv) {
|
||||
#include "dispatch.h"
|
||||
|
||||
domemdump = 0;
|
||||
dolinecleararg = 0;
|
||||
bootarg = NULL;
|
||||
bootfile[0] = 0;
|
||||
gv.pmap32bits = 0;
|
||||
@@ -4465,6 +4472,9 @@ int main (int argc, char **argv) {
|
||||
} else if (strcmp(argv[i],"-memdump") == 0) {
|
||||
domemdump = 1;
|
||||
|
||||
} else if (strcmp(argv[i],"-dolineclear") == 0) {
|
||||
dolinecleararg = 1;
|
||||
|
||||
} else if (strcmp(argv[i],"-ss") == 0) {
|
||||
if (i+1 < argc && argv[i+1][0] != '-') {
|
||||
sscanf(argv[++i],"%o", &templ);
|
||||
@@ -4603,14 +4613,16 @@ int main (int argc, char **argv) {
|
||||
setlinebuf(gv.tracefile);
|
||||
else if (strcmp(argv[i],"tlb") == 0)
|
||||
gv.traceflags |= T_TLB;
|
||||
else if (strcmp(argv[i],"smlc") == 0)
|
||||
gv.traceflags |= T_SMLC;
|
||||
else if (isdigit(argv[i][0]) && strlen(argv[i]) <= 3 && sscanf(argv[i],"%d", &templ) == 1)
|
||||
gv.traceuser = 0100000 | (templ<<6); /* form OWNERL for user # */
|
||||
else if (isdigit(argv[i][0]) && sscanf(argv[i],"%d", &templ) == 1)
|
||||
gv.traceinstcount = templ;
|
||||
else if (strlen(argv[i]) == 6 && sscanf(argv[i],"%o", &templ) == 1)
|
||||
gv.traceuser = templ; /* specify OWNERL directly */
|
||||
else if (strlen(argv[i]) == 4 && sscanf(argv[i],"%o", &templ) == 1)
|
||||
gv.traceseg = templ; /* specify RPH segno */
|
||||
else if (argv[i][0] == '#' && sscanf(argv[i]+1,"%d", &templ) == 1)
|
||||
gv.traceinstcount = templ;
|
||||
else if (strlen(argv[i]) <= 8 && argv[i][0] != '-') {
|
||||
if (gv.numtraceprocs >= MAXTRACEPROCS)
|
||||
fprintf(stderr,"Only %d trace procs are allowed\n", MAXTRACEPROCS);
|
||||
@@ -4701,6 +4713,7 @@ int main (int argc, char **argv) {
|
||||
/* finish setting up tracing after all options are read, ie, maps */
|
||||
|
||||
#ifndef NOTRACE
|
||||
TRACEA("Trace file initialized\n");
|
||||
TRACEA("Trace flags = 0x%x\n", gv.traceflags);
|
||||
gv.savetraceflags = gv.traceflags;
|
||||
gv.traceflags = 0;
|
||||
@@ -4710,6 +4723,14 @@ int main (int argc, char **argv) {
|
||||
TRACEA("Tracing enabled for all users\n");
|
||||
if (gv.traceinstcount != 0)
|
||||
TRACEA("Tracing enabled after instruction %u\n", gv.traceinstcount);
|
||||
if (gv.traceseg != 0)
|
||||
{
|
||||
TRACEA("Tracing enabled for segment %04o\n", gv.traceseg);
|
||||
/* This could be splattering other settings that aren't really
|
||||
compatible with RPH trace. C'est la vie? */
|
||||
gv.savetraceflags |= T_FLOW;
|
||||
gv.tracetriggered = 0;
|
||||
}
|
||||
for (i=0; i<gv.numtraceprocs; i++) {
|
||||
for (j=0; j<numsyms; j++) {
|
||||
if (strcasecmp(mapsym[j].symname, traceprocs[i].name) == 0 && mapsym[j].symtype == 'e') {
|
||||
@@ -4936,6 +4957,11 @@ fetch:
|
||||
#endif
|
||||
|
||||
#ifndef NOTRACE
|
||||
if (gv.traceseg != 0)
|
||||
if (gv.traceseg == (RPH & 0xFFF))
|
||||
gv.tracetriggered = 1;
|
||||
else
|
||||
gv.tracetriggered = 0;
|
||||
gv.traceflags = 0;
|
||||
if (gv.tracetriggered &&
|
||||
(gv.instcount >= gv.traceinstcount) &&
|
||||
@@ -6276,15 +6302,33 @@ d_hlt: /* 000000 */
|
||||
if (bootarg) {
|
||||
printf("\nCPU halt, instruction #%u at %o/%o %s: %o %o ^%06o^\nA='%o/%d B='%o/%d L='%o/%d X=%o/%d", gv.instcount, RPH, RPL, searchloadmap(gv.prevpc,' '), get16t(gv.prevpc), get16t(gv.prevpc+1), lights, getcrs16(A), getcrs16s(A), getcrs16(B), getcrs16s(B), getcrs32(A), getcrs32s(A), getcrs16(X), getcrs16s(X));
|
||||
while (1) {
|
||||
int n;
|
||||
static int ttydev;
|
||||
ttydev = open("/dev/tty", O_RDWR, 0);
|
||||
if (ttydev < 0) {
|
||||
perror(" error opening /dev/tty");
|
||||
fatal(NULL);
|
||||
}
|
||||
printf("\nPress Enter to continue, h to halt... ");
|
||||
utempa = getchar();
|
||||
fflush(stdout);
|
||||
utempa = ' ';
|
||||
n = 0;
|
||||
while (n == 0)
|
||||
n = read(ttydev, &utempa, 1);
|
||||
/* utempa = getchar(); */
|
||||
printf("\n");
|
||||
if (utempa == '\r' || utempa == '\n')
|
||||
{
|
||||
close(ttydev);
|
||||
goto fetch;
|
||||
}
|
||||
if (utempa == 'h')
|
||||
{
|
||||
close(ttydev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fatal("CPU halt");
|
||||
|
||||
d_pim: /* 000205 (R-mode) */
|
||||
|
||||
2
emdev.h
2
emdev.h
@@ -2224,3 +2224,5 @@ int devdisk (int class, int func, int device) {
|
||||
#include "devpnc.h"
|
||||
|
||||
#include "devamlc.h"
|
||||
|
||||
#include "devsmlc.h"
|
||||
|
||||
2
makefile
2
makefile
@@ -7,7 +7,7 @@ all_deps = makefile
|
||||
em_objs = em.o em
|
||||
em_deps = \
|
||||
em.c regs.h emdev.h ea64v.h ea32i.h fp.h dispatch.h geom.h \
|
||||
devpnc.h devamlc.h swap.h
|
||||
devpnc.h devamlc.h devsmlc.h swap.h
|
||||
|
||||
CFLAGS =
|
||||
# Uncomment for building on SmartOS/Solaris:
|
||||
|
||||
35
util/cmraw.c
Normal file
35
util/cmraw.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Show approximate minimum clock resolution
|
||||
Derived from the example in the linux man page for clock_gettime() */
|
||||
|
||||
#define _XOPEN_SOURCE 600
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void displayClock(clockid_t clock, char *name)
|
||||
{
|
||||
struct timespec ts;
|
||||
time_t oldsec;
|
||||
long oldnsec;
|
||||
|
||||
clock_gettime(clock, &ts);
|
||||
oldsec = ts.tv_sec;
|
||||
oldnsec = ts.tv_nsec;
|
||||
while (ts.tv_sec == oldsec && ts.tv_nsec == oldnsec)
|
||||
{
|
||||
if (clock_gettime(clock, &ts) == -1) {
|
||||
perror("clock_gettime");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
printf("%-15s: %10ld sec %09ld nsec\n", name,
|
||||
(long) ts.tv_sec - oldsec, ts.tv_nsec - oldnsec);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
displayClock(CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW");
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user