aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas <nbnoll@eml.cc>2021-11-20 17:07:23 -0800
committerNicholas <nbnoll@eml.cc>2021-11-20 17:07:23 -0800
commitc9a32c1a43d2bdded07eaa45732c3a6e195a5442 (patch)
treecb7e9cb8c34cbe6551b801eff4201afcf71dd0fd
parente97c8c469db0aa27985dab2879dc1f14905c7387 (diff)
Chore: cleaned up the exit code to cleanly interface with libc
We use weak linking to ensure we clean up at exit time correctly. If libc is linked, then we call our cleanup function by registering an atexit callback with the library. If libc is not linked, we have a weak symbol that results in a noop. Similarly, if we call rt·exit while linked with libc, this immediately calls libc's exit (which will call our cleanup as we registered it). If we are not linked to libc, exit() is given as a weak link to a noop function.
-rw-r--r--include/base.h2
-rw-r--r--include/base/gz.h2
-rw-r--r--include/base/io.h31
-rw-r--r--include/rt.h1
-rw-r--r--include/sys.h2
-rw-r--r--include/u.h1
-rw-r--r--src/base/bufio/internal.h2
-rw-r--r--src/base/fmt/test.c9
-rw-r--r--src/base/gz/seek.c2
-rw-r--r--src/base/io/interface.c2
-rw-r--r--src/base/io/seek.c4
-rw-r--r--src/rules.mk8
-rw-r--r--sys/linux/amd64/arch/constants.h23
-rw-r--r--sys/linux/arm/arch/constants.h20
-rw-r--r--sys/linux/arm64/arch/constants.h22
-rw-r--r--sys/linux/i386/arch/constants.h20
-rw-r--r--sys/linux/port/os/constants.h13
-rw-r--r--sys/linux/riscv64/arch/constants.h20
-rw-r--r--sys/rt/atexit.c49
-rw-r--r--sys/rt/boot.c4
-rw-r--r--sys/rt/dummy.c3
-rw-r--r--sys/rt/exit.c19
-rw-r--r--sys/rules.mk1
23 files changed, 215 insertions, 45 deletions
diff --git a/include/base.h b/include/base.h
index a7e9319..d532a85 100644
--- a/include/base.h
+++ b/include/base.h
@@ -3,8 +3,8 @@
// ------------------------------------------------------------------------
// standard library
+#include <rt.h>
#include <sys.h>
-#include <arch/types.h>
// TODO: remove dependency system headers
#include <assert.h>
diff --git a/include/base/gz.h b/include/base/gz.h
index 3b3a830..ac241d3 100644
--- a/include/base/gz.h
+++ b/include/base/gz.h
@@ -25,5 +25,5 @@ int gz·putbyte(gz·Stream *s, byte str);
int gz·putstring(gz·Stream *s, byte *str);
int gz·printf(gz·Stream *s, byte *fmt, ...);
int gz·flush(gz·Stream *s);
-int gz·seek(gz·Stream *s, long off, enum SeekPos whence);
+int gz·seek(gz·Stream *s, long off, int whence);
long gz·tell(gz·Stream *s);
diff --git a/include/base/io.h b/include/base/io.h
index 5e0f1e0..5d31282 100644
--- a/include/base/io.h
+++ b/include/base/io.h
@@ -1,12 +1,5 @@
#pragma once
-enum SeekPos
-{
- seek·cur = SEEK_CUR,
- seek·set = SEEK_SET,
- seek·end = SEEK_END
-};
-
typedef struct io·Reader
{
int (*read)(void*, int sz, int n, void *buf);
@@ -22,7 +15,7 @@ extern io·Peeker sys·Peeker;
typedef struct io·Seeker
{
- int (*seek)(void *skr, long off, enum SeekPos whence);
+ int (*seek)(void *skr, long off, int whence);
long (*tell)(void *skr);
} io·Seeker;
extern io·Seeker sys·Seeker;
@@ -93,10 +86,11 @@ int io·putbyte(io·Stream *s, byte c);
int io·putstring(io·Stream *s, string str);
int io·write(io·Stream *s, int sz, int n, void *buf);
int io·flush(io·Stream *s);
-int io·seek(io·Stream *s, long off, enum SeekPos whence);
+int io·seek(io·Stream *s, long off, int whence);
long io·tell(io·Stream *s);
/* buffered i/o */
+typedef struct io·Header io·Header;
typedef struct io·Buffer io·Buffer;
#define iota(x) (1 << (x))
@@ -116,21 +110,26 @@ enum
};
#undef iota
-struct io·Buffer
+struct io·Header
{
- int state, id, flag;
+ int state, fd, flag;
struct{
- int in; /* negative number of bytes at end */
- int out; /* number of bytes at start */
- int line; /* number of bytes after last readline */
+ int in; /* negative number of bytes at end */
+ int out; /* number of bytes at start */
+ int ln; /* number of bytes after last readline */
} off;
intptr pos, cap; /* position in file, capacity of buffer */
uchar *b,*g,*e; /* start, good bytes, end of byte pointers */
- uchar bytes[];
+};
+
+struct io·Buffer
+{
+ io·Header;
+ uchar bytes[io·BufLen+io·BufUngets];
};
int bio·init(io·Buffer *io, int fd, int mode);
-int bio·initcap(io·Buffer *io, int fd, int mode, int cap);
+int bio·initcap(io·Header *io, int fd, int mode, int cap, uchar *buf);
/* basic os helpers */
/* XXX: find a better location for this */
diff --git a/include/rt.h b/include/rt.h
index 43357cd..ce92af0 100644
--- a/include/rt.h
+++ b/include/rt.h
@@ -12,4 +12,5 @@ extern struct rt·Context
extern char **rt·environ;
+int rt·atexit(void (*func)(void *), void *arg);
void noreturn rt·exit(int code);
diff --git a/include/sys.h b/include/sys.h
index 0c703a8..e983f2a 100644
--- a/include/sys.h
+++ b/include/sys.h
@@ -2,6 +2,7 @@
/* types declarations */
#include <arch/types.h>
+#include <arch/constants.h>
#include <os/types.h>
#include <os/constants.h>
@@ -14,6 +15,7 @@
#define sys·ORead 0x0u
#define sys·OWrite 0x1u
#define sys·ORdwr 0x2u
+#define sys·OExec sys·OPath
/* seek */
#define sys·SeekSet 0u
diff --git a/include/u.h b/include/u.h
index d415d82..fe251ac 100644
--- a/include/u.h
+++ b/include/u.h
@@ -112,6 +112,7 @@ typedef __builtin_va_list va_list;
#define noreturn _Noreturn
#define hidden __attribute__((__visibility__("hidden")))
#define weakalias(old, new) extern __typeof(old) new __attribute__((weak, alias(#old)))
+#define weaklink __attribute__((weak))
/* offsets */
#define offsetof(t, d) __builtin_offsetof(t, d)
diff --git a/src/base/bufio/internal.h b/src/base/bufio/internal.h
index a1a006a..a59e787 100644
--- a/src/base/bufio/internal.h
+++ b/src/base/bufio/internal.h
@@ -1,2 +1,4 @@
#include <u.h>
#include <base.h>
+
+#define header(io) ((io·Header*)(io))
diff --git a/src/base/fmt/test.c b/src/base/fmt/test.c
index 73f5e7c..3f7f070 100644
--- a/src/base/fmt/test.c
+++ b/src/base/fmt/test.c
@@ -15,9 +15,18 @@ Xfmt(fmt·State *io)
return fmt·write(io, "(real=%g,imag=%g)", c.r, c.i);
}
+static void
+saygoodbye(void *arg)
+{
+ intptr n;
+ sys·write(1, 9, "goodbye\n", &n);
+}
+
int
main(int argc, char *argv[])
{
+ rt·atexit(saygoodbye, nil);
+
fmt·print("basic tests\n");
fmt·print("\tx: %x\n", 0x87654321);
fmt·print("\tu: %u\n", 0x87654321);
diff --git a/src/base/gz/seek.c b/src/base/gz/seek.c
index 328886d..8230a79 100644
--- a/src/base/gz/seek.c
+++ b/src/base/gz/seek.c
@@ -1,7 +1,7 @@
#include "internal.h"
int
-gz·seek(gz·Stream *s, long off, enum SeekPos whence)
+gz·seek(gz·Stream *s, long off, int whence)
{
return gzseek(s, off, whence);
}
diff --git a/src/base/io/interface.c b/src/base/io/interface.c
index bc9d5ff..80469bf 100644
--- a/src/base/io/interface.c
+++ b/src/base/io/interface.c
@@ -44,7 +44,7 @@ int
static
int
-·seek(void *skr, long off, enum SeekPos whence)
+·seek(void *skr, long off, int whence)
{
return io·seek((io·Stream *)skr, off, whence);
}
diff --git a/src/base/io/seek.c b/src/base/io/seek.c
index d0e7488..1be4ee7 100644
--- a/src/base/io/seek.c
+++ b/src/base/io/seek.c
@@ -1,7 +1,7 @@
#include "internal.h"
int
-io·seek(io·Stream *s, long off, enum SeekPos origin)
+io·seek(io·Stream *s, long off, int whence)
{
- return fseek(s, off, origin);
+ return fseek(s, off, whence);
}
diff --git a/src/rules.mk b/src/rules.mk
index 8e8594c..368479c 100644
--- a/src/rules.mk
+++ b/src/rules.mk
@@ -8,10 +8,10 @@ include $(DIR)/rules.mk
DIR := $(d)/base
include $(DIR)/rules.mk
-# DIR := $(d)/libmath
-# include $(DIR)/rules.mk
+DIR := $(d)/libmath
+include $(DIR)/rules.mk
-# DIR := $(d)/libbio
-# include $(DIR)/rules.mk
+DIR := $(d)/libbio
+include $(DIR)/rules.mk
include share/pop.mk
diff --git a/sys/linux/amd64/arch/constants.h b/sys/linux/amd64/arch/constants.h
new file mode 100644
index 0000000..1949bdf
--- /dev/null
+++ b/sys/linux/amd64/arch/constants.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#define sys·OCreate 0100
+#define sys·OUnique 0200
+#define sys·ONoTTY 0400
+#define sys·OTrunc 01000
+#define sys·OAppend 02000
+#define sys·ONoBlock 04000
+#define sys·ODsync 010000
+#define sys·OSync 04010000
+#define sys·ORsync 04010000
+#define sys·ODirectory 0200000
+#define sys·ONoFollow 0400000
+#define sys·OCloseExec 02000000
+
+#define sys·OAsync 020000
+#define sys·ODirect 040000
+#define sys·OLargeFile 0
+#define sys·ONoATime 01000000
+#define sys·OPath 010000000
+#define sys·OTempFile 020200000
+
+#define SYS·HAVE_FCNTL
diff --git a/sys/linux/arm/arch/constants.h b/sys/linux/arm/arch/constants.h
new file mode 100644
index 0000000..149c2eb
--- /dev/null
+++ b/sys/linux/arm/arch/constants.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#define sys·OCreate 0100
+#define sys·OUnique 0200
+#define sys·ONoTTY 0400
+#define sys·OTrunc 01000
+#define sys·OAppend 02000
+#define sys·ONoBlock 04000
+#define sys·ODsync 010000
+#define sys·OSync 04010000
+#define sys·ORsync 04010000
+#define sys·ODirectory 040000
+#define sys·ONoFollow 0100000
+#define sys·OCloseExec 02000000
+#define sys·OAsync 020000
+#define sys·ODirect 0200000
+#define sys·OLargeFile 0400000
+#define sys·ONoATime 01000000
+#define sys·OPath 010000000
+#define sys·OTempFile 020040000
diff --git a/sys/linux/arm64/arch/constants.h b/sys/linux/arm64/arch/constants.h
new file mode 100644
index 0000000..f3f42e5
--- /dev/null
+++ b/sys/linux/arm64/arch/constants.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#define sys·OCreate 0100
+#define sys·OUnique 0200
+#define sys·ONoTTY 0400
+#define sys·OTrunc 01000
+#define sys·OAppend 02000
+#define sys·ONoBlock 04000
+#define sys·ODsync 010000
+#define sys·OSync 04010000
+#define sys·ORsync 04010000
+#define sys·ODirectory 040000
+#define sys·ONoFollow 0100000
+#define sys·OCloseExec 02000000
+#define sys·OAsync 020000
+#define sys·ODirect 0200000
+#define sys·OLargeFile 0400000
+#define sys·ONoATime 01000000
+#define sys·OPath 010000000
+#define sys·OTempFile 020040000
+
+#define SYS·HAVE_FCNTL
diff --git a/sys/linux/i386/arch/constants.h b/sys/linux/i386/arch/constants.h
new file mode 100644
index 0000000..ff6aa0c
--- /dev/null
+++ b/sys/linux/i386/arch/constants.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#define sys·OCreate 0100
+#define sys·OUnique 0200
+#define sys·ONoTTY 0400
+#define sys·OTrunc 01000
+#define sys·OAppend 02000
+#define sys·ONoBlock 04000
+#define sys·ODsync 010000
+#define sys·OSync 04010000
+#define sys·ORsync 04010000
+#define sys·ODirectory 0200000
+#define sys·ONoFollow 0400000
+#define sys·OCloseExec 02000000
+#define sys·OAsync 020000
+#define sys·ODirect 040000
+#define sys·OLargeFile 0100000
+#define sys·ONoATime 01000000
+#define sys·OPath 010000000
+#define sys·OTempfile 020200000
diff --git a/sys/linux/port/os/constants.h b/sys/linux/port/os/constants.h
index 8fb913f..ffe8610 100644
--- a/sys/linux/port/os/constants.h
+++ b/sys/linux/port/os/constants.h
@@ -1,18 +1,5 @@
#pragma once
-/* open */
-#define sys·OCreate 0x40u
-#define sys·ONoTTY 0x100u
-#define sys·OTrunc 0x200u
-#define sys·OAppend 0x400u
-#define sys·ONoBlock 0x800u
-#define sys·OSync 0x1000u
-#define sys·OAsync 0x2000u
-#define sys·OLargeFile 0x8000u
-#define sys·ODirectory 0x10000u
-#define sys·ONoFollow 0x20000u
-#define sys·OTmpFile 0x410000u
-
/* device modes */
#define sys·ModeFile 0170000
#define sys·ModeDir 0040000
diff --git a/sys/linux/riscv64/arch/constants.h b/sys/linux/riscv64/arch/constants.h
new file mode 100644
index 0000000..ff6aa0c
--- /dev/null
+++ b/sys/linux/riscv64/arch/constants.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#define sys·OCreate 0100
+#define sys·OUnique 0200
+#define sys·ONoTTY 0400
+#define sys·OTrunc 01000
+#define sys·OAppend 02000
+#define sys·ONoBlock 04000
+#define sys·ODsync 010000
+#define sys·OSync 04010000
+#define sys·ORsync 04010000
+#define sys·ODirectory 0200000
+#define sys·ONoFollow 0400000
+#define sys·OCloseExec 02000000
+#define sys·OAsync 020000
+#define sys·ODirect 040000
+#define sys·OLargeFile 0100000
+#define sys·ONoATime 01000000
+#define sys·OPath 010000000
+#define sys·OTempfile 020200000
diff --git a/sys/rt/atexit.c b/sys/rt/atexit.c
new file mode 100644
index 0000000..208cc6e
--- /dev/null
+++ b/sys/rt/atexit.c
@@ -0,0 +1,49 @@
+#include <u.h>
+#include <rt.h>
+
+#define COUNT 32
+
+static struct cleaner
+{
+ struct cleaner *next;
+ void (*clean[COUNT])(void *);
+ void *arg[COUNT];
+} arena, *head;
+static int slot;
+
+void weaklink exit(int code){};
+
+void
+rt·clean(void)
+{
+ void (*clean)(void *), *arg;
+ /*LOCK*/
+ for(; head; head=head->next, slot=COUNT) {
+ while(slot-- > 0){
+ arg = head->arg[slot];
+ clean = head->clean[slot];
+ /* UNLOCK */
+ clean(arg);
+ /* LOCK */
+ }
+ }
+}
+
+int
+rt·atexit(void (*clean)(void *), void *arg)
+{
+ /* LOCK */
+ if(!head)
+ head = &arena;
+
+ /* we need malloc... */
+ if(slot==COUNT)
+ return -1;
+
+ head->arg[slot] = arg;
+ head->clean[slot] = clean;
+ slot++;
+
+ /* UNLOCK */
+ return 0;
+}
diff --git a/sys/rt/boot.c b/sys/rt/boot.c
index 320a596..8c6616d 100644
--- a/sys/rt/boot.c
+++ b/sys/rt/boot.c
@@ -3,7 +3,10 @@
#include <elf.h>
/* tell linker to go find */
+int atexit(void (*)(void));
int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv);
+
+void rt·clean(void);
void rt·guardstack(void);
#define NAUX 38
@@ -30,6 +33,7 @@ rt·boot(int (*main)(), int argc, char **argv, void (*init)(), void (*fini)(), v
rt·init(env, argv[0]);
/* ring libc, anyone home? */
+ atexit(rt·clean);
__libc_start_main(main, argc, argv);
/* no? ok we continue on if there is no libc linked */
diff --git a/sys/rt/dummy.c b/sys/rt/dummy.c
index f123d16..0cef224 100644
--- a/sys/rt/dummy.c
+++ b/sys/rt/dummy.c
@@ -4,3 +4,6 @@
/* provide a dummy implementation if libc is not linked */
static int noop(int (*main)(), int argc, char **argv) { return 0; }
weakalias(noop, __libc_start_main);
+
+static int noop2(void (*func)(void)) { return 0; }
+weakalias(noop, atexit);
diff --git a/sys/rt/exit.c b/sys/rt/exit.c
index e6027b7..386a1bf 100644
--- a/sys/rt/exit.c
+++ b/sys/rt/exit.c
@@ -2,10 +2,13 @@
#include <rt.h>
#include <syscall.h>
-/* XXX:
- * if we are here, we are in charge, call exit syscalls
- * think of better way to encapsulate these syscalls?
- */
+/* tell linker to go find */
+void noreturn exit(int code);
+
+/* if did not call rt·atexit, then don't pull it in */
+static void noop(void){}
+weakalias(noop, rt·clean);
+
static noreturn void
rt·shutdown(int code)
{
@@ -14,14 +17,18 @@ rt·shutdown(int code)
if(rt·context.exit)
rt·context.exit();
+ /* XXX: better way to encapsulate these calls? */
_syscall1(·ExitGroup, code);
for(;;)
_syscall1(·Exit, code);
}
-weakalias(rt·shutdown, exit);
noreturn void
rt·exit(int code)
{
- rt·shutdown(code);
+ /* ring libc, anyone home? */
+ exit(code);
+ /* if we are here, we are in charge, shut it down */
+ rt·clean();
+ rt·shutdown(code);
}
diff --git a/sys/rules.mk b/sys/rules.mk
index 4bba9aa..1cbe50e 100644
--- a/sys/rules.mk
+++ b/sys/rules.mk
@@ -20,6 +20,7 @@ RT1_OBJ := $(patsubst $(SYS_DIR)/rt/%, $(OBJ_DIR)/rt/%, $(RT1_OBJ))
RT3_SRC := \
$(SYS_DIR)/rt/stack.c\
$(SYS_DIR)/rt/dummy.c\
+ $(SYS_DIR)/rt/atexit.c\
$(SYS_DIR)/rt/exit.c
RT3_OBJ := $(filter %.o, $(RT3_SRC:.c=.o))