aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/9term/AIX.c2
-rw-r--r--src/cmd/9term/bsdpty.c2
-rw-r--r--src/cmd/acme/regx.c3
-rw-r--r--src/cmd/auxstats/AIX.c9
-rw-r--r--src/cmd/devdraw/devdraw.c30
-rw-r--r--src/cmd/devdraw/devdraw.h28
-rw-r--r--src/cmd/devdraw/latin1.c39
-rw-r--r--src/cmd/devdraw/mac-screen.m43
-rw-r--r--src/cmd/devdraw/mklatinkbd.c2
-rw-r--r--src/cmd/devdraw/srv.c35
-rw-r--r--src/cmd/devdraw/x11-screen.c21
-rw-r--r--src/cmd/diff/diffreg.c3
-rw-r--r--src/cmd/draw/mc.c3
-rw-r--r--src/cmd/ed.c41
-rw-r--r--src/cmd/fontsrv/a.h9
-rw-r--r--src/cmd/fontsrv/mac.c6
-rw-r--r--src/cmd/fontsrv/main.c53
-rw-r--r--src/cmd/fontsrv/x11.c22
-rw-r--r--src/cmd/mk/archive.c4
-rw-r--r--src/cmd/mk/env.c3
-rw-r--r--src/cmd/mkfile2
-rw-r--r--src/cmd/rc/rc.h6
-rw-r--r--src/cmd/vbackup/mount-AIX.c1
-rw-r--r--src/lib9/create.c75
-rw-r--r--src/lib9/dirread.c207
-rw-r--r--src/lib9/fmt/fmt.c21
-rw-r--r--src/lib9/mkfile3
-rw-r--r--src/lib9/open.c293
-rw-r--r--src/lib9/readcons.c2
-rw-r--r--src/lib9/seek.c8
-rw-r--r--src/libdiskfs/ext2.h33
-rw-r--r--src/libdiskfs/ffs.h33
-rw-r--r--src/libdraw/drawclient.c2
-rw-r--r--src/libdraw/drawfcall.c15
-rw-r--r--src/libdraw/event.c2
-rw-r--r--src/libdraw/openfont.c2
-rw-r--r--src/libip/AIX.c1
-rw-r--r--src/libmach/AIX.c1
-rw-r--r--src/libthread/Darwin-x86_64-asm.s44
-rw-r--r--src/libthread/channel.c2
-rw-r--r--src/libthread/pthread.c37
-rw-r--r--src/libthread/sysofiles.sh4
-rw-r--r--src/libthread/thread.c92
-rw-r--r--src/libthread/threadimpl.h69
-rw-r--r--src/mkenv1
-rw-r--r--src/mkfile3
-rw-r--r--src/mkhdr3
-rw-r--r--src/mkmk.sh8
48 files changed, 804 insertions, 524 deletions
diff --git a/src/cmd/9term/AIX.c b/src/cmd/9term/AIX.c
new file mode 100644
index 00000000..b7ccbf0f
--- /dev/null
+++ b/src/cmd/9term/AIX.c
@@ -0,0 +1,2 @@
+#define TIOCSCTTY 0x540E
+#include "bsdpty.c"
diff --git a/src/cmd/9term/bsdpty.c b/src/cmd/9term/bsdpty.c
index d64e4c2f..3710a18d 100644
--- a/src/cmd/9term/bsdpty.c
+++ b/src/cmd/9term/bsdpty.c
@@ -5,7 +5,9 @@
#include <errno.h>
#include <grp.h>
#include <termios.h>
+#ifdef HAS_SYS_TERMIOS
#include <sys/termios.h>
+#endif
#ifdef __linux__
#include <pty.h>
#endif
diff --git a/src/cmd/acme/regx.c b/src/cmd/acme/regx.c
index 56ea900c..ec574563 100644
--- a/src/cmd/acme/regx.c
+++ b/src/cmd/acme/regx.c
@@ -15,6 +15,9 @@
Rangeset sel;
Rune *lastregexp;
+#undef class
+#define class regxclass /* some systems declare "class" in system headers */
+
/*
* Machine Information
*/
diff --git a/src/cmd/auxstats/AIX.c b/src/cmd/auxstats/AIX.c
new file mode 100644
index 00000000..33ebdedc
--- /dev/null
+++ b/src/cmd/auxstats/AIX.c
@@ -0,0 +1,9 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+void (*statfn[])(int) =
+{
+ 0
+};
diff --git a/src/cmd/devdraw/devdraw.c b/src/cmd/devdraw/devdraw.c
index b4c373ad..234cdf1b 100644
--- a/src/cmd/devdraw/devdraw.c
+++ b/src/cmd/devdraw/devdraw.c
@@ -14,6 +14,8 @@
#include <drawfcall.h>
#include "devdraw.h"
+QLock drawlk;
+
static int drawuninstall(Client*, int);
static Memimage* drawinstall(Client*, int, Memimage*, DScreen*);
static void drawfreedimage(Client*, DImage*);
@@ -47,14 +49,14 @@ gfx_replacescreenimage(Client *c, Memimage *m)
*/
Memimage *om;
- qlock(&c->drawlk);
+ qlock(&drawlk);
om = c->screenimage;
c->screenimage = m;
m->screenref = 1;
if(om && --om->screenref == 0){
_freememimage(om);
}
- qunlock(&c->drawlk);
+ qunlock(&drawlk);
gfx_mouseresized(c);
}
@@ -142,9 +144,9 @@ addflush(Client *c, Rectangle r)
// and gfx thread might be blocked on drawlk trying to install a new screen
// during a resize.
rpc_gfxdrawunlock();
- qunlock(&c->drawlk);
- rpc_flush(c, fr);
- qlock(&c->drawlk);
+ qunlock(&drawlk);
+ c->impl->rpc_flush(c, fr);
+ qlock(&drawlk);
rpc_gfxdrawlock();
}
}
@@ -187,9 +189,9 @@ drawflush(Client *c)
// and gfx thread might be blocked on drawlk trying to install a new screen
// during a resize.
rpc_gfxdrawunlock();
- qunlock(&c->drawlk);
- rpc_flush(c, r);
- qlock(&c->drawlk);
+ qunlock(&drawlk);
+ c->impl->rpc_flush(c, r);
+ qlock(&drawlk);
rpc_gfxdrawlock();
}
}
@@ -614,7 +616,7 @@ drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
int
draw_dataread(Client *cl, void *a, int n)
{
- qlock(&cl->drawlk);
+ qlock(&drawlk);
if(cl->readdata == nil){
werrstr("no draw data");
goto err;
@@ -627,11 +629,11 @@ draw_dataread(Client *cl, void *a, int n)
memmove(a, cl->readdata, cl->nreaddata);
free(cl->readdata);
cl->readdata = nil;
- qunlock(&cl->drawlk);
+ qunlock(&drawlk);
return n;
err:
- qunlock(&cl->drawlk);
+ qunlock(&drawlk);
return -1;
}
@@ -656,7 +658,7 @@ draw_datawrite(Client *client, void *v, int n)
Refreshfn reffn;
Refx *refx;
- qlock(&client->drawlk);
+ qlock(&drawlk);
rpc_gfxdrawlock();
a = v;
m = 0;
@@ -1431,7 +1433,7 @@ draw_datawrite(Client *client, void *v, int n)
}
}
rpc_gfxdrawunlock();
- qunlock(&client->drawlk);
+ qunlock(&drawlk);
return oldn - n;
Enodrawimage:
@@ -1502,6 +1504,6 @@ Ebadarg:
error:
werrstr("%s", err);
rpc_gfxdrawunlock();
- qunlock(&client->drawlk);
+ qunlock(&drawlk);
return -1;
}
diff --git a/src/cmd/devdraw/devdraw.h b/src/cmd/devdraw/devdraw.h
index 6829ab32..261d04d1 100644
--- a/src/cmd/devdraw/devdraw.h
+++ b/src/cmd/devdraw/devdraw.h
@@ -7,6 +7,7 @@ typedef struct Mousebuf Mousebuf;
typedef struct Tagbuf Tagbuf;
typedef struct Client Client;
+typedef struct ClientImpl ClientImpl;
typedef struct DImage DImage;
typedef struct DScreen DScreen;
typedef struct CScreen CScreen;
@@ -43,6 +44,20 @@ struct Tagbuf
int wi;
};
+struct ClientImpl
+{
+ void (*rpc_resizeimg)(Client*);
+ void (*rpc_resizewindow)(Client*, Rectangle);
+ void (*rpc_setcursor)(Client*, Cursor*, Cursor2*);
+ void (*rpc_setlabel)(Client*, char*);
+ void (*rpc_setmouse)(Client*, Point);
+ void (*rpc_topwin)(Client*);
+ void (*rpc_bouncemouse)(Client*, Mouse);
+ void (*rpc_flush)(Client*, Rectangle);
+};
+
+extern QLock drawlk;
+
struct Client
{
int rfd;
@@ -56,10 +71,9 @@ struct Client
char* wsysid;
- // drawlk protects the draw data structures.
+ // drawlk protects the draw data structures for all clients.
// It can be acquired by an RPC thread or a graphics thread
// but must not be held on one thread while waiting for the other.
- QLock drawlk;
/*Ref r;*/
DImage* dimage[NHASH];
CScreen* cscreen;
@@ -82,6 +96,7 @@ struct Client
int nname;
DName* name;
int namevers;
+ ClientImpl* impl;
// Only accessed/modified by the graphics thread.
const void* view;
@@ -196,17 +211,8 @@ void gfx_started(void);
Memimage *rpc_attach(Client*, char*, char*);
char* rpc_getsnarf(void);
void rpc_putsnarf(char*);
-void rpc_resizeimg(Client*);
-void rpc_resizewindow(Client*, Rectangle);
-void rpc_serve(Client*);
-void rpc_setcursor(Client*, Cursor*, Cursor2*);
-void rpc_setlabel(Client*, char*);
-void rpc_setmouse(Client*, Point);
void rpc_shutdown(void);
-void rpc_topwin(Client*);
void rpc_main(void);
-void rpc_bouncemouse(Client*, Mouse);
-void rpc_flush(Client*, Rectangle);
// rpc_gfxdrawlock and rpc_gfxdrawunlock
// are called around drawing operations to lock and unlock
diff --git a/src/cmd/devdraw/latin1.c b/src/cmd/devdraw/latin1.c
index a3d13a08..87c0be45 100644
--- a/src/cmd/devdraw/latin1.c
+++ b/src/cmd/devdraw/latin1.c
@@ -17,16 +17,15 @@ static struct cvlist
};
/*
- * Given 5 characters k[0]..k[4], find the rune or return -1 for failure.
+ * Given 5 characters k[0]..k[n], find the rune or return -1 for failure.
*/
static long
-unicode(Rune *k)
+unicode(Rune *k, int n)
{
long i, c;
- k++; /* skip 'X' */
c = 0;
- for(i=0; i<4; i++,k++){
+ for(i=0; i<n; i++,k++){
c <<= 4;
if('0'<=*k && *k<='9')
c += *k-'0';
@@ -36,6 +35,8 @@ unicode(Rune *k)
c += 10 + *k-'A';
else
return -1;
+ if(c > Runemax)
+ return -1;
}
return c;
}
@@ -53,10 +54,32 @@ latin1(Rune *k, int n)
char* p;
if(k[0] == 'X'){
- if(n>=5)
- return unicode(k);
- else
- return -5;
+ if(n < 2)
+ return -2;
+ if(k[1] == 'X') {
+ if(n < 3)
+ return -3;
+ if(k[2] == 'X') {
+ if(n < 9) {
+ if(unicode(k+3, n-3) < 0)
+ return -1;
+ return -(n+1);
+ }
+ return unicode(k+3, 6);
+ }
+ if(n < 7) {
+ if(unicode(k+2, n-2) < 0)
+ return -1;
+ return -(n+1);
+ }
+ return unicode(k+2, 5);
+ }
+ if(n < 5) {
+ if(unicode(k+1, n-1) < 0)
+ return -1;
+ return -(n+1);
+ }
+ return unicode(k+1, 4);
}
for(l=latintab; l->ld!=0; l++)
diff --git a/src/cmd/devdraw/mac-screen.m b/src/cmd/devdraw/mac-screen.m
index c6e58341..ad9c029e 100644
--- a/src/cmd/devdraw/mac-screen.m
+++ b/src/cmd/devdraw/mac-screen.m
@@ -37,6 +37,26 @@ static void setprocname(const char*);
static uint keycvt(uint);
static uint msec(void);
+static void rpc_resizeimg(Client*);
+static void rpc_resizewindow(Client*, Rectangle);
+static void rpc_setcursor(Client*, Cursor*, Cursor2*);
+static void rpc_setlabel(Client*, char*);
+static void rpc_setmouse(Client*, Point);
+static void rpc_topwin(Client*);
+static void rpc_bouncemouse(Client*, Mouse);
+static void rpc_flush(Client*, Rectangle);
+
+static ClientImpl macimpl = {
+ rpc_resizeimg,
+ rpc_resizewindow,
+ rpc_setcursor,
+ rpc_setlabel,
+ rpc_setmouse,
+ rpc_topwin,
+ rpc_bouncemouse,
+ rpc_flush
+};
+
@class DrawView;
@class DrawLayer;
@@ -201,6 +221,7 @@ rpc_attach(Client *c, char *label, char *winsize)
{
LOG(@"attachscreen(%s, %s)", label, winsize);
+ c->impl = &macimpl;
dispatch_sync(dispatch_get_main_queue(), ^(void) {
@autoreleasepool {
DrawView *view = [[DrawView new] attach:c winsize:winsize label:label];
@@ -302,7 +323,7 @@ rpc_attach(Client *c, char *label, char *winsize)
// rpc_topwin moves the window to the top of the desktop.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_topwin(Client *c)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -319,7 +340,7 @@ rpc_topwin(Client *c)
// rpc_setlabel updates the client window's label.
// If label == nil, the call is a no-op.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_setlabel(Client *client, char *label)
{
DrawView *view = (__bridge DrawView*)client->view;
@@ -344,7 +365,7 @@ rpc_setlabel(Client *client, char *label)
// rpc_setcursor updates the client window's cursor image.
// Either c and c2 are both non-nil, or they are both nil to use the default arrow.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
{
DrawView *view = (__bridge DrawView*)client->view;
@@ -460,7 +481,7 @@ rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
// rpc_flush flushes changes to view.img's rectangle r
// to the on-screen window, making them visible.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_flush(Client *client, Rectangle r)
{
DrawView *view = (__bridge DrawView*)client->view;
@@ -474,17 +495,17 @@ rpc_flush(Client *client, Rectangle r)
if(!rectclip(&r, Rect(0, 0, self.dlayer.texture.width, self.dlayer.texture.height)) || !rectclip(&r, self.img->r))
return;
- // self.client->drawlk protects the pixel data in self.img.
+ // drawlk protects the pixel data in self.img.
// In addition to avoiding a technical data race,
// the lock avoids drawing partial updates, which makes
// animations like sweeping windows much less flickery.
- qlock(&self.client->drawlk);
+ qlock(&drawlk);
[self.dlayer.texture
replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r))
mipmapLevel:0
withBytes:byteaddr(self.img, Pt(r.min.x, r.min.y))
bytesPerRow:self.img->width*sizeof(u32int)];
- qunlock(&self.client->drawlk);
+ qunlock(&drawlk);
NSRect nr = NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r));
dispatch_time_t time;
@@ -506,7 +527,7 @@ rpc_flush(Client *client, Rectangle r)
// rpc_resizeimg forces the client window to discard its current window and make a new one.
// It is called when the user types Cmd-R to toggle whether retina mode is forced.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_resizeimg(Client *c)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -541,7 +562,7 @@ rpc_resizeimg(Client *c)
// rpc_resizewindow asks for the client window to be resized to size r.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_resizewindow(Client *c, Rectangle r)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -696,7 +717,7 @@ rpc_resizewindow(Client *c, Rectangle r)
// rpc_setmouse moves the mouse cursor.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_setmouse(Client *c, Point p)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -1095,7 +1116,7 @@ rpc_putsnarf(char *s)
// rpc_bouncemouse is for sending a mouse event
// back to the X11 window manager rio(1).
// Does not apply here.
-void
+static void
rpc_bouncemouse(Client *c, Mouse m)
{
}
diff --git a/src/cmd/devdraw/mklatinkbd.c b/src/cmd/devdraw/mklatinkbd.c
index db34b6ec..50dd26b0 100644
--- a/src/cmd/devdraw/mklatinkbd.c
+++ b/src/cmd/devdraw/mklatinkbd.c
@@ -191,7 +191,7 @@ readfile(char *fname)
r = strtol(line, nil, 16);
p = strchr(line, ' ');
- if(r == 0 || p != line+4 || p[0] != ' ' || p[1] != ' ') {
+ if(r == 0 || (p != line+4 && p != line+5) || p[0] != ' ' || (p == line+4 && p[1] != ' ')) {
fprint(2, "%s:%d: cannot parse line\n", fname, lineno);
continue;
}
diff --git a/src/cmd/devdraw/srv.c b/src/cmd/devdraw/srv.c
index 570091bc..05a08fda 100644
--- a/src/cmd/devdraw/srv.c
+++ b/src/cmd/devdraw/srv.c
@@ -54,6 +54,7 @@ threadmain(int argc, char **argv)
usage();
}ARGEND
+ memimageinit();
fmtinstall('H', encodefmt);
if((p = getenv("DEVDRAWTRACE")) != nil)
trace = atoi(p);
@@ -202,8 +203,11 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Tinit:
- memimageinit();
i = rpc_attach(c, m->label, m->winsize);
+ if(i == nil) {
+ replyerror(c, m);
+ break;
+ }
draw_initdisplaymemimage(c, i);
replymsg(c, m);
break;
@@ -225,6 +229,7 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Trdkbd:
+ case Trdkbd4:
qlock(&c->eventlk);
if((c->kbdtags.wi+1)%nelem(c->kbdtags.t) == c->kbdtags.ri) {
qunlock(&c->eventlk);
@@ -232,7 +237,7 @@ runmsg(Client *c, Wsysmsg *m)
replyerror(c, m);
break;
}
- c->kbdtags.t[c->kbdtags.wi++] = m->tag;
+ c->kbdtags.t[c->kbdtags.wi++] = (m->tag<<1) | (m->type==Trdkbd4);
if(c->kbdtags.wi == nelem(c->kbdtags.t))
c->kbdtags.wi = 0;
c->kbd.stall = 0;
@@ -241,35 +246,35 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Tmoveto:
- rpc_setmouse(c, m->mouse.xy);
+ c->impl->rpc_setmouse(c, m->mouse.xy);
replymsg(c, m);
break;
case Tcursor:
if(m->arrowcursor)
- rpc_setcursor(c, nil, nil);
+ c->impl->rpc_setcursor(c, nil, nil);
else {
scalecursor(&m->cursor2, &m->cursor);
- rpc_setcursor(c, &m->cursor, &m->cursor2);
+ c->impl->rpc_setcursor(c, &m->cursor, &m->cursor2);
}
replymsg(c, m);
break;
case Tcursor2:
if(m->arrowcursor)
- rpc_setcursor(c, nil, nil);
+ c->impl->rpc_setcursor(c, nil, nil);
else
- rpc_setcursor(c, &m->cursor, &m->cursor2);
+ c->impl->rpc_setcursor(c, &m->cursor, &m->cursor2);
replymsg(c, m);
break;
case Tbouncemouse:
- rpc_bouncemouse(c, m->mouse);
+ c->impl->rpc_bouncemouse(c, m->mouse);
replymsg(c, m);
break;
case Tlabel:
- rpc_setlabel(c, m->label);
+ c->impl->rpc_setlabel(c, m->label);
replymsg(c, m);
break;
@@ -306,12 +311,12 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Ttop:
- rpc_topwin(c);
+ c->impl->rpc_topwin(c);
replymsg(c, m);
break;
case Tresize:
- rpc_resizewindow(c, m->rect);
+ c->impl->rpc_resizewindow(c, m->rect);
replymsg(c, m);
break;
}
@@ -353,13 +358,17 @@ replymsg(Client *c, Wsysmsg *m)
static void
matchkbd(Client *c)
{
+ int tag;
Wsysmsg m;
if(c->kbd.stall)
return;
while(c->kbd.ri != c->kbd.wi && c->kbdtags.ri != c->kbdtags.wi){
+ tag = c->kbdtags.t[c->kbdtags.ri++];
m.type = Rrdkbd;
- m.tag = c->kbdtags.t[c->kbdtags.ri++];
+ if(tag&1)
+ m.type = Rrdkbd4;
+ m.tag = tag>>1;
if(c->kbdtags.ri == nelem(c->kbdtags.t))
c->kbdtags.ri = 0;
m.rune = c->kbd.r[c->kbd.ri++];
@@ -513,7 +522,7 @@ gfx_keystroke(Client *c, int ch)
else
c->forcedpi = 225;
qunlock(&c->eventlk);
- rpc_resizeimg(c);
+ c->impl->rpc_resizeimg(c);
return;
}
if(!c->kbd.alting){
diff --git a/src/cmd/devdraw/x11-screen.c b/src/cmd/devdraw/x11-screen.c
index 62f49f2f..0bbc25d6 100644
--- a/src/cmd/devdraw/x11-screen.c
+++ b/src/cmd/devdraw/x11-screen.c
@@ -40,6 +40,26 @@ static void _xmovewindow(Xwin *w, Rectangle r);
static int _xtoplan9kbd(XEvent *e);
static int _xselect(XEvent *e);
+static void rpc_resizeimg(Client*);
+static void rpc_resizewindow(Client*, Rectangle);
+static void rpc_setcursor(Client*, Cursor*, Cursor2*);
+static void rpc_setlabel(Client*, char*);
+static void rpc_setmouse(Client*, Point);
+static void rpc_topwin(Client*);
+static void rpc_bouncemouse(Client*, Mouse);
+static void rpc_flush(Client*, Rectangle);
+
+static ClientImpl x11impl = {
+ rpc_resizeimg,
+ rpc_resizewindow,
+ rpc_setcursor,
+ rpc_setlabel,
+ rpc_setmouse,
+ rpc_topwin,
+ rpc_bouncemouse,
+ rpc_flush
+};
+
static Xwin*
newxwin(Client *c)
{
@@ -51,6 +71,7 @@ newxwin(Client *c)
w->client = c;
w->next = _x.windows;
_x.windows = w;
+ c->impl = &x11impl;
c->view = w;
return w;
}
diff --git a/src/cmd/diff/diffreg.c b/src/cmd/diff/diffreg.c
index ed4d17b8..478c1b1b 100644
--- a/src/cmd/diff/diffreg.c
+++ b/src/cmd/diff/diffreg.c
@@ -66,6 +66,9 @@
* 3*(number of k-candidates installed), typically about
* 6n words for files of length n.
*/
+
+#define class diffclass
+
/* TIDY THIS UP */
struct cand {
int x;
diff --git a/src/cmd/draw/mc.c b/src/cmd/draw/mc.c
index ee112194..f1bcc82a 100644
--- a/src/cmd/draw/mc.c
+++ b/src/cmd/draw/mc.c
@@ -9,7 +9,10 @@
*/
#include <u.h>
#include <sys/ioctl.h>
+#include <termios.h>
+#ifdef HAS_SYS_TERMIOS
#include <sys/termios.h>
+#endif
#include <libc.h>
#include <draw.h>
#include <bio.h>
diff --git a/src/cmd/ed.c b/src/cmd/ed.c
index 8b0f36e5..a04f0d3f 100644
--- a/src/cmd/ed.c
+++ b/src/cmd/ed.c
@@ -21,6 +21,12 @@ enum
EOF = -1
};
+enum
+{
+ LINELEN = 70, /* max number of glyphs in a display line */
+ BELL = 6 /* A char could require up to BELL glyphs to display */
+};
+
void (*oldhup)(int);
void (*oldquit)(int);
int* addr1;
@@ -40,7 +46,7 @@ int ichanged;
int io;
Biobuf iobuf;
int lastc;
-char line[70];
+char line[LINELEN];
Rune* linebp;
Rune linebuf[LBSIZE];
int listf;
@@ -1543,7 +1549,7 @@ putchr(int ac)
*lp++ = 'n';
}
} else {
- if(col > (72-6-2)) {
+ if(col > (LINELEN-BELL)) {
col = 8;
*lp++ = '\\';
*lp++ = '\n';
@@ -1558,15 +1564,32 @@ putchr(int ac)
if(c == '\t')
c = 't';
col++;
- } else
- if(c<' ' || c>='\177') {
+ } else if (c<' ' || c=='\177') {
*lp++ = '\\';
*lp++ = 'x';
- *lp++ = hex[c>>12];
- *lp++ = hex[c>>8&0xF];
- *lp++ = hex[c>>4&0xF];
- c = hex[c&0xF];
+ *lp++ = hex[(c>>4)&0xF];
+ c = hex[c&0xF];
+ col += 3;
+ } else if (c>'\177' && c<=0xFFFF) {
+ *lp++ = '\\';
+ *lp++ = 'u';
+ *lp++ = hex[(c>>12)&0xF];
+ *lp++ = hex[(c>>8)&0xF];
+ *lp++ = hex[(c>>4)&0xF];
+ c = hex[c&0xF];
col += 5;
+ } else if (c>0xFFFF) {
+ *lp++ = '\\';
+ *lp++ = 'U';
+ *lp++ = hex[(c>>28)&0xF];
+ *lp++ = hex[(c>>24)&0xF];
+ *lp++ = hex[(c>>20)&0xF];
+ *lp++ = hex[(c>>16)&0xF];
+ *lp++ = hex[(c>>12)&0xF];
+ *lp++ = hex[(c>>8)&0xF];
+ *lp++ = hex[(c>>4)&0xF];
+ c = hex[c&0xF];
+ col += 9;
}
}
}
@@ -1574,7 +1597,7 @@ putchr(int ac)
rune = c;
lp += runetochar(lp, &rune);
- if(c == '\n' || lp >= &line[sizeof(line)-5]) {
+ if(c == '\n' || lp >= &line[LINELEN-BELL]) {
linp = line;
write(oflag? 2: 1, line, lp-line);
return;
diff --git a/src/cmd/fontsrv/a.h b/src/cmd/fontsrv/a.h
index 164b1bd6..2eeb404f 100644
--- a/src/cmd/fontsrv/a.h
+++ b/src/cmd/fontsrv/a.h
@@ -4,19 +4,22 @@ int nxfont;
enum {
SubfontSize = 32,
- SubfontMask = (1<<16)/SubfontSize - 1,
+ MaxSubfont = (Runemax+1)/SubfontSize,
};
struct XFont
{
char *name;
int loaded;
- uchar range[(1<<16)/SubfontSize]; // range[i] == whether to have subfont i*SubfontSize to (i+1)*SubfontSize - 1.
- int nrange;
+ uchar range[MaxSubfont]; // range[i] = fontfile starting at i*SubfontSize exists
+ ushort file[MaxSubfont]; // file[i] == fontfile i's lo rune / SubfontSize
+ int nfile;
int unit;
double height;
double originy;
void (*loadheight)(XFont*, int, int*, int*);
+ char *fonttext;
+ int nfonttext;
// fontconfig workarround, as FC_FULLNAME does not work for matching fonts.
char *fontfile;
diff --git a/src/cmd/fontsrv/mac.c b/src/cmd/fontsrv/mac.c
index b4dadd90..9829b5a8 100644
--- a/src/cmd/fontsrv/mac.c
+++ b/src/cmd/fontsrv/mac.c
@@ -200,9 +200,12 @@ load(XFont *f)
f->loadheight = fontheight;
// enable all Unicode ranges
+ if(nelem(f->file) > 0xffff)
+ sysfatal("too many subfiles"); // f->file holds ushorts
for(i=0; i<nelem(f->range); i++) {
f->range[i] = 1;
- f->nrange++;
+ f->file[i] = i;
+ f->nfile++;
}
}
@@ -233,7 +236,6 @@ mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
if(font == nil)
return nil;
-
bbox = CTFontGetBoundingBox(font);
x = (int)(bbox.size.width*2 + 0.99999999);
diff --git a/src/cmd/fontsrv/main.c b/src/cmd/fontsrv/main.c
index ebab6249..b2189be9 100644
--- a/src/cmd/fontsrv/main.c
+++ b/src/cmd/fontsrv/main.c
@@ -52,7 +52,7 @@ enum
#define QFONT(p) (((p) >> 4) & 0xFFFF)
#define QSIZE(p) (((p) >> 20) & 0xFF)
#define QANTIALIAS(p) (((p) >> 28) & 0x1)
-#define QRANGE(p) (((p) >> 29) & SubfontMask)
+#define QRANGE(p) (((p) >> 29) & 0xFFFFFF)
static int sizes[] = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 28 };
static vlong
@@ -102,7 +102,7 @@ dostat(vlong path, Qid *qid, Dir *dir)
case Qfontfile:
f = &xfont[QFONT(path)];
load(f);
- length = 11+1+11+1+f->nrange*(6+1+6+1+9+1);
+ length = 11+1+11+1+f->nfile*(6+1+6+1+9+1);
name = "font";
break;
@@ -189,9 +189,9 @@ xwalk1(Fid *fid, char *name, Qid *qid)
goto NotFound;
p++;
n = strtoul(p, &p, 16);
- if(p != name+5 || n%SubfontSize != 0 || strcmp(p, ".bit") != 0 || !f->range[(n/SubfontSize) & SubfontMask])
+ if(p < name+5 || p > name+5 && name[1] == '0' || n%SubfontSize != 0 || n/SubfontSize >= MaxSubfont || strcmp(p, ".bit") != 0 || !f->range[n/SubfontSize])
goto NotFound;
- path += Qsubfontfile - Qsizedir + qpath(0, 0, 0, 0, (n/SubfontSize) & SubfontMask);
+ path += Qsubfontfile - Qsizedir + qpath(0, 0, 0, 0, n/SubfontSize);
break;
}
Found:
@@ -229,7 +229,6 @@ sizegen(int i, Dir *d, void *v)
vlong path;
Fid *fid;
XFont *f;
- int j;
fid = v;
path = fid->qid.path;
@@ -240,15 +239,10 @@ sizegen(int i, Dir *d, void *v)
i--;
f = &xfont[QFONT(path)];
load(f);
- for(j=0; j<nelem(f->range); j++) {
- if(f->range[j] == 0)
- continue;
- if(i == 0) {
- path += Qsubfontfile - Qsizedir;
- path += qpath(0, 0, 0, 0, j);
- goto Done;
- }
- i--;
+ if(i < f->nfile) {
+ path += Qsubfontfile - Qsizedir;
+ path += qpath(0, 0, 0, 0, f->file[i]);
+ goto Done;
}
return -1;
@@ -315,23 +309,22 @@ xread(Req *r)
readstr(r, "font missing\n");
break;
}
- height = 0;
- ascent = 0;
- if(f->unit > 0) {
- height = f->height * (int)QSIZE(path)/f->unit + 0.99999999;
- ascent = height - (int)(-f->originy * (int)QSIZE(path)/f->unit + 0.99999999);
- }
- if(f->loadheight != nil)
- f->loadheight(f, QSIZE(path), &height, &ascent);
- fmtprint(&fmt, "%11d %11d\n", height, ascent);
- for(i=0; i<nelem(f->range); i++) {
- if(f->range[i] == 0)
- continue;
- fmtprint(&fmt, "0x%04x 0x%04x x%04x.bit\n", i*SubfontSize, ((i+1)*SubfontSize) - 1, i*SubfontSize);
+ if(f->fonttext == nil) {
+ height = 0;
+ ascent = 0;
+ if(f->unit > 0) {
+ height = f->height * (int)QSIZE(path)/f->unit + 0.99999999;
+ ascent = height - (int)(-f->originy * (int)QSIZE(path)/f->unit + 0.99999999);
+ }
+ if(f->loadheight != nil)
+ f->loadheight(f, QSIZE(path), &height, &ascent);
+ fmtprint(&fmt, "%11d %11d\n", height, ascent);
+ for(i=0; i<f->nfile; i++)
+ fmtprint(&fmt, "0x%04x 0x%04x x%04x.bit\n", f->file[i]*SubfontSize, ((f->file[i]+1)*SubfontSize) - 1, f->file[i]*SubfontSize);
+ f->fonttext = fmtstrflush(&fmt);
+ f->nfonttext = strlen(f->fonttext);
}
- data = fmtstrflush(&fmt);
- readstr(r, data);
- free(data);
+ readbuf(r, f->fonttext, f->nfonttext);
break;
case Qsubfontfile:
f = &xfont[QFONT(path)];
diff --git a/src/cmd/fontsrv/x11.c b/src/cmd/fontsrv/x11.c
index 0f6b97bb..c1d10197 100644
--- a/src/cmd/fontsrv/x11.c
+++ b/src/cmd/fontsrv/x11.c
@@ -61,6 +61,7 @@ load(XFont *f)
FT_Error e;
FT_ULong charcode;
FT_UInt glyph_index;
+ int i;
if(f->loaded)
return;
@@ -78,27 +79,30 @@ load(XFont *f)
}
f->unit = face->units_per_EM;
f->height = (int)((face->ascender - face->descender) * 1.35);
- f->originy = face->descender; // bbox.yMin (or descender) is negative, becase the baseline is y-coord 0
+ f->originy = face->descender * 1.35; // bbox.yMin (or descender) is negative, because the baseline is y-coord 0
for(charcode=FT_Get_First_Char(face, &glyph_index); glyph_index != 0;
charcode=FT_Get_Next_Char(face, charcode, &glyph_index)) {
int idx = charcode/SubfontSize;
- if(charcode > 0xffff)
+ if(charcode > Runemax)
break;
- if(!f->range[idx]) {
+ if(!f->range[idx])
f->range[idx] = 1;
- f->nrange++;
- }
}
+ FT_Done_Face(face);
+
// libdraw expects U+0000 to be present
- if(!f->range[0]) {
+ if(!f->range[0])
f->range[0] = 1;
- f->nrange++;
- }
- FT_Done_Face(face);
+
+ // fix up file list
+ for(i=0; i<nelem(f->range); i++)
+ if(f->range[i])
+ f->file[f->nfile++] = i;
+
f->loaded = 1;
}
diff --git a/src/cmd/mk/archive.c b/src/cmd/mk/archive.c
index 5b0c1d00..6d646979 100644
--- a/src/cmd/mk/archive.c
+++ b/src/cmd/mk/archive.c
@@ -1,5 +1,9 @@
#include "mk.h"
+#if defined(__AIX__)
+#define ARMAG "<bigaf>\n"
+#else
#define ARMAG "!<arch>\n"
+#endif
#define SARMAG (sizeof(ARMAG) - sizeof(""))
#define ARFMAG "`\n"
diff --git a/src/cmd/mk/env.c b/src/cmd/mk/env.c
index d7c6481d..e01aa21a 100644
--- a/src/cmd/mk/env.c
+++ b/src/cmd/mk/env.c
@@ -123,7 +123,8 @@ buildenv(Job *j, int slot)
qp = strchr(cp+1, ')');
if(qp){
*qp = 0;
- strcpy(w->s, cp+1);
+ /* strcpy, but might overlap */
+ memmove(w->s, cp+1, strlen(cp+1)+1);
l = &w->next;
w = w->next;
continue;
diff --git a/src/cmd/mkfile b/src/cmd/mkfile
index bc8b5a0d..2d0c657e 100644
--- a/src/cmd/mkfile
+++ b/src/cmd/mkfile
@@ -27,7 +27,7 @@ $PLAN9/bin/lex: $PLAN9/bin/yacc
# This should not be necessary.
$PLAN9/bin/yacc: $O.yacc
- install -c $O.yacc $PLAN9/bin/yacc
+ $INSTALL -c $O.yacc $PLAN9/bin/yacc
$O.yacc: yacc.$O
$LD -o $target $prereq
yacc.$O: yacc.c
diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h
index 46ff9510..2fd6758b 100644
--- a/src/cmd/rc/rc.h
+++ b/src/cmd/rc/rc.h
@@ -33,6 +33,12 @@
#undef pipe /* so that /dev/fd works */
#define searchpath rcsearchpath /* avoid new libc function */
+/* some systems define a global "var", "thread" */
+#undef var
+#define var rcvar
+#undef thread
+#define thread rcthread
+
typedef struct tree tree;
typedef struct word word;
typedef struct io io;
diff --git a/src/cmd/vbackup/mount-AIX.c b/src/cmd/vbackup/mount-AIX.c
new file mode 100644
index 00000000..3dde4fdf
--- /dev/null
+++ b/src/cmd/vbackup/mount-AIX.c
@@ -0,0 +1 @@
+#include "mount-none.c"
diff --git a/src/lib9/create.c b/src/lib9/create.c
deleted file mode 100644
index e4e3c715..00000000
--- a/src/lib9/create.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#define _GNU_SOURCE /* for Linux O_DIRECT */
-#include <u.h>
-#define NOPLAN9DEFINES
-#include <sys/file.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <libc.h>
-#include <sys/stat.h>
-#ifndef O_DIRECT
-#define O_DIRECT 0
-#endif
-
-int
-p9create(char *path, int mode, ulong perm)
-{
- int fd, cexec, umode, rclose, lock, rdwr;
- struct flock fl;
-
- rdwr = mode&3;
- lock = mode&OLOCK;
- cexec = mode&OCEXEC;
- rclose = mode&ORCLOSE;
- mode &= ~(ORCLOSE|OCEXEC|OLOCK);
-
- /* XXX should get mode mask right? */
- fd = -1;
- if(perm&DMDIR){
- if(mode != OREAD){
- werrstr("bad mode in directory create");
- goto out;
- }
- if(mkdir(path, perm&0777) < 0)
- goto out;
- fd = open(path, O_RDONLY);
- }else{
- umode = (mode&3)|O_CREAT|O_TRUNC;
- mode &= ~(3|OTRUNC);
- if(mode&ODIRECT){
- umode |= O_DIRECT;
- mode &= ~ODIRECT;
- }
- if(mode&OEXCL){
- umode |= O_EXCL;
- mode &= ~OEXCL;
- }
- if(mode&OAPPEND){
- umode |= O_APPEND;
- mode &= ~OAPPEND;
- }
- if(mode){
- werrstr("unsupported mode in create");
- goto out;
- }
- fd = open(path, umode, perm);
- }
-out:
- if(fd >= 0){
- if(lock){
- fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;
- fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0;
- if(fcntl(fd, F_SETLK, &fl) < 0){
- close(fd);
- werrstr("lock: %r");
- return -1;
- }
- }
- if(cexec)
- fcntl(fd, F_SETFL, FD_CLOEXEC);
- if(rclose)
- remove(path);
- }
- return fd;
-}
diff --git a/src/lib9/dirread.c b/src/lib9/dirread.c
deleted file mode 100644
index c232eb8d..00000000
--- a/src/lib9/dirread.c
+++ /dev/null
@@ -1,207 +0,0 @@
-#include <u.h>
-#define NOPLAN9DEFINES
-#include <libc.h>
-#include <sys/stat.h>
-#include <dirent.h>
-
-extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*);
-
-#if defined(__linux__)
-static int
-mygetdents(int fd, struct dirent *buf, int n)
-{
- off_t off;
- int nn;
-
- /* This doesn't match the man page, but it works in Debian with a 2.2 kernel */
- off = p9seek(fd, 0, 1);
- nn = getdirentries(fd, (void*)buf, n, &off);
- return nn;
-}
-#elif defined(__APPLE__)
-static int
-mygetdents(int fd, struct dirent *buf, int n)
-{
- long off;
- return getdirentries(fd, (void*)buf, n, &off);
-}
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
-static int
-mygetdents(int fd, struct dirent *buf, int n)
-{
- off_t off;
- return getdirentries(fd, (void*)buf, n, &off);
-}
-#elif defined(__sun__) || defined(__NetBSD__) || defined(__OpenBSD__)
-static int
-mygetdents(int fd, struct dirent *buf, int n)
-{
- return getdents(fd, (void*)buf, n);
-}
-#elif defined(__AIX__)
-static int
-mygetdents(int fd, struct dirent *buf, int n)
-{
- return getdirent(fd, (void*)buf, n);
-}
-#endif
-
-#if defined(__DragonFly__)
-static inline int d_reclen(struct dirent *de) { return _DIRENT_DIRSIZ(de); }
-#else
-static inline int d_reclen(struct dirent *de) { return de->d_reclen; }
-#endif
-
-static int
-countde(char *p, int n)
-{
- char *e;
- int m;
- struct dirent *de;
-
- e = p+n;
- m = 0;
- while(p < e){
- de = (struct dirent*)p;
- if(d_reclen(de) <= 4+2+2+1 || p+d_reclen(de) > e)
- break;
- if(de->d_name[0]=='.' && de->d_name[1]==0)
- de->d_name[0] = 0;
- else if(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0)
- de->d_name[0] = 0;
- m++;
- p += d_reclen(de);
- }
- return m;
-}
-
-static int
-dirpackage(int fd, char *buf, int n, Dir **dp)
-{
- int oldwd;
- char *p, *str, *estr;
- int i, nstr, m;
- struct dirent *de;
- struct stat st, lst;
- Dir *d;
-
- n = countde(buf, n);
- if(n <= 0)
- return n;
-
- if((oldwd = open(".", O_RDONLY)) < 0)
- return -1;
- if(fchdir(fd) < 0)
- return -1;
-
- p = buf;
- nstr = 0;
-
- for(i=0; i<n; i++){
- de = (struct dirent*)p;
- memset(&lst, 0, sizeof lst);
- if(de->d_name[0] == 0)
- /* nothing */ {}
- else if(lstat(de->d_name, &lst) < 0)
- de->d_name[0] = 0;
- else{
- st = lst;
- if(S_ISLNK(lst.st_mode))
- stat(de->d_name, &st);
- nstr += _p9dir(&lst, &st, de->d_name, nil, nil, nil);
- }
- p += d_reclen(de);
- }
-
- d = malloc(sizeof(Dir)*n+nstr);
- if(d == nil){
- fchdir(oldwd);
- close(oldwd);
- return -1;
- }
- str = (char*)&d[n];
- estr = str+nstr;
-
- p = buf;
- m = 0;
- for(i=0; i<n; i++){
- de = (struct dirent*)p;
- if(de->d_name[0] != 0 && lstat(de->d_name, &lst) >= 0){
- st = lst;
- if((lst.st_mode&S_IFMT) == S_IFLNK)
- stat(de->d_name, &st);
- _p9dir(&lst, &st, de->d_name, &d[m++], &str, estr);
- }
- p += d_reclen(de);
- }
-
- fchdir(oldwd);
- close(oldwd);
- *dp = d;
- return m;
-}
-
-long
-dirread(int fd, Dir **dp)
-{
- char *buf;
- struct stat st;
- int n;
-
- *dp = 0;
-
- if(fstat(fd, &st) < 0)
- return -1;
-
- if(st.st_blksize < 8192)
- st.st_blksize = 8192;
-
- buf = malloc(st.st_blksize);
- if(buf == nil)
- return -1;
-
- n = mygetdents(fd, (void*)buf, st.st_blksize);
- if(n < 0){
- free(buf);
- return -1;
- }
- n = dirpackage(fd, buf, n, dp);
- free(buf);
- return n;
-}
-
-
-long
-dirreadall(int fd, Dir **d)
-{
- uchar *buf, *nbuf;
- long n, ts;
- struct stat st;
-
- if(fstat(fd, &st) < 0)
- return -1;
-
- if(st.st_blksize < 8192)
- st.st_blksize = 8192;
-
- buf = nil;
- ts = 0;
- for(;;){
- nbuf = realloc(buf, ts+st.st_blksize);
- if(nbuf == nil){
- free(buf);
- return -1;
- }
- buf = nbuf;
- n = mygetdents(fd, (void*)(buf+ts), st.st_blksize);
- if(n <= 0)
- break;
- ts += n;
- }
- if(ts >= 0)
- ts = dirpackage(fd, (char*)buf, ts, d);
- free(buf);
- if(ts == 0 && n < 0)
- return -1;
- return ts;
-}
diff --git a/src/lib9/fmt/fmt.c b/src/lib9/fmt/fmt.c
index a86482c3..47b186a4 100644
--- a/src/lib9/fmt/fmt.c
+++ b/src/lib9/fmt/fmt.c
@@ -1,7 +1,28 @@
/* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
#include <stdarg.h>
#include <string.h>
+
+/*
+ * As of 2020, older systems like RHEL 6 and AIX still do not have C11 atomics.
+ * On those systems, make the code use volatile int accesses and hope for the best.
+ * (Most uses of fmtinstall are not actually racing with calls to print that lookup
+ * formats. The code used volatile here for years without too many problems,
+ * even though that's technically racy. A mutex is not OK, because we want to
+ * be able to call print from signal handlers.)
+ *
+ * RHEL is using an old GCC (atomics were added in GCC 4.9).
+ * AIX is using its own IBM compiler (XL C).
+ */
+#if __IBMC__ || !__clang__ && __GNUC__ && (__GNUC__ < 4 || (__GNUC__==4 && __GNUC_MINOR__<9))
+#warning not using C11 stdatomic on legacy system
+#define _Atomic volatile
+#define atomic_load(x) (*(x))
+#define atomic_store(x, y) (*(x)=(y))
+#define ATOMIC_VAR_INIT(x) (x)
+#else
#include <stdatomic.h>
+#endif
+
#include "plan9.h"
#include "fmt.h"
#include "fmtdef.h"
diff --git a/src/lib9/mkfile b/src/lib9/mkfile
index 7c37de42..db267dfe 100644
--- a/src/lib9/mkfile
+++ b/src/lib9/mkfile
@@ -86,14 +86,12 @@ LIB9OFILES=\
convM2D.$O\
convM2S.$O\
convS2M.$O\
- create.$O\
crypt.$O\
ctime.$O\
dial.$O\
dirfstat.$O\
dirfwstat.$O\
dirmodefmt.$O\
- dirread.$O\
dirstat.$O\
dirwstat.$O\
dup.$O\
@@ -141,7 +139,6 @@ LIB9OFILES=\
readn.$O\
rfork.$O\
searchpath.$O\
- seek.$O\
sendfd.$O\
sleep.$O\
strdup.$O\
diff --git a/src/lib9/open.c b/src/lib9/open.c
index a0573ae7..2354268b 100644
--- a/src/lib9/open.c
+++ b/src/lib9/open.c
@@ -1,11 +1,140 @@
#define _GNU_SOURCE /* for Linux O_DIRECT */
#include <u.h>
-#define NOPLAN9DEFINES
+#include <dirent.h>
+#include <errno.h>
#include <sys/file.h>
+#include <sys/stat.h>
+#define NOPLAN9DEFINES
#include <libc.h>
-#ifndef O_DIRECT
-#define O_DIRECT 0
-#endif
+
+static struct {
+ Lock lk;
+ DIR **d;
+ int nd;
+} dirs;
+
+static int
+dirput(int fd, DIR *d)
+{
+ int i, nd;
+ DIR **dp;
+
+ if(fd < 0) {
+ werrstr("invalid fd");
+ return -1;
+ }
+ lock(&dirs.lk);
+ if(fd >= dirs.nd) {
+ nd = dirs.nd*2;
+ if(nd <= fd)
+ nd = fd+1;
+ dp = realloc(dirs.d, nd*sizeof dirs.d[0]);
+ if(dp == nil) {
+ werrstr("out of memory");
+ unlock(&dirs.lk);
+ return -1;
+ }
+ for(i=dirs.nd; i<nd; i++)
+ dp[i] = nil;
+ dirs.d = dp;
+ dirs.nd = nd;
+ }
+ dirs.d[fd] = d;
+ unlock(&dirs.lk);
+ return 0;
+}
+
+static DIR*
+dirget(int fd)
+{
+ DIR *d;
+
+ lock(&dirs.lk);
+ d = nil;
+ if(0 <= fd && fd < dirs.nd)
+ d = dirs.d[fd];
+ unlock(&dirs.lk);
+ return d;
+}
+
+static DIR*
+dirdel(int fd)
+{
+ DIR *d;
+
+ lock(&dirs.lk);
+ d = nil;
+ if(0 <= fd && fd < dirs.nd) {
+ d = dirs.d[fd];
+ dirs.d[fd] = nil;
+ }
+ unlock(&dirs.lk);
+ return d;
+}
+
+int
+p9create(char *path, int mode, ulong perm)
+{
+ int fd, cexec, umode, rclose, lock, rdwr;
+ struct flock fl;
+
+ rdwr = mode&3;
+ lock = mode&OLOCK;
+ cexec = mode&OCEXEC;
+ rclose = mode&ORCLOSE;
+ mode &= ~(ORCLOSE|OCEXEC|OLOCK);
+
+ /* XXX should get mode mask right? */
+ fd = -1;
+ if(perm&DMDIR){
+ if(mode != OREAD){
+ werrstr("bad mode in directory create");
+ goto out;
+ }
+ if(mkdir(path, perm&0777) < 0)
+ goto out;
+ fd = open(path, O_RDONLY);
+ }else{
+ umode = (mode&3)|O_CREAT|O_TRUNC;
+ mode &= ~(3|OTRUNC);
+ if(mode&ODIRECT){
+ umode |= O_DIRECT;
+ mode &= ~ODIRECT;
+ }
+ if(mode&OEXCL){
+ umode |= O_EXCL;
+ mode &= ~OEXCL;
+ }
+ if(mode&OAPPEND){
+ umode |= O_APPEND;
+ mode &= ~OAPPEND;
+ }
+ if(mode){
+ werrstr("unsupported mode in create");
+ goto out;
+ }
+ fd = open(path, umode, perm);
+ }
+out:
+ if(fd >= 0){
+ if(lock){
+ fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ if(fcntl(fd, F_SETLK, &fl) < 0){
+ close(fd);
+ werrstr("lock: %r");
+ return -1;
+ }
+ }
+ if(cexec)
+ fcntl(fd, F_SETFL, FD_CLOEXEC);
+ if(rclose)
+ remove(path);
+ }
+ return fd;
+}
int
p9open(char *name, int mode)
@@ -13,6 +142,8 @@ p9open(char *name, int mode)
int cexec, rclose;
int fd, umode, lock, rdwr;
struct flock fl;
+ struct stat st;
+ DIR *d;
rdwr = mode&3;
umode = rdwr;
@@ -55,8 +186,162 @@ p9open(char *name, int mode)
}
if(cexec)
fcntl(fd, F_SETFL, FD_CLOEXEC);
+ if(fstat(fd, &st) >= 0 && S_ISDIR(st.st_mode)) {
+ d = fdopendir(fd);
+ if(d == nil) {
+ close(fd);
+ return -1;
+ }
+ if(dirput(fd, d) < 0) {
+ closedir(d);
+ return -1;
+ }
+ }
if(rclose)
remove(name);
}
return fd;
}
+
+vlong
+p9seek(int fd, vlong offset, int whence)
+{
+ DIR *d;
+
+ if((d = dirget(fd)) != nil) {
+ if(whence == 1 && offset == 0)
+ return telldir(d);
+ if(whence == 0) {
+ seekdir(d, offset);
+ return 0;
+ }
+ werrstr("bad seek in directory");
+ return -1;
+ }
+
+ return lseek(fd, offset, whence);
+}
+
+int
+p9close(int fd)
+{
+ DIR *d;
+
+ if((d = dirdel(fd)) != nil)
+ return closedir(d);
+ return close(fd);
+}
+
+typedef struct DirBuild DirBuild;
+struct DirBuild {
+ Dir *d;
+ int nd;
+ int md;
+ char *str;
+ char *estr;
+};
+
+extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*);
+
+static int
+dirbuild1(DirBuild *b, struct stat *lst, struct stat *st, char *name)
+{
+ int i, nstr;
+ Dir *d;
+ int md, mstr;
+ char *lo, *hi, *newlo;
+
+ nstr = _p9dir(lst, st, name, nil, nil, nil);
+ if(b->md-b->nd < 1 || b->estr-b->str < nstr) {
+ // expand either d space or str space or both.
+ md = b->md;
+ if(b->md-b->nd < 1) {
+ md *= 2;
+ if(md < 16)
+ md = 16;
+ }
+ mstr = b->estr-(char*)&b->d[b->md];
+ if(b->estr-b->str < nstr) {
+ mstr += nstr;
+ mstr += mstr/2;
+ }
+ if(mstr < 512)
+ mstr = 512;
+ d = realloc(b->d, md*sizeof d[0] + mstr);
+ if(d == nil)
+ return -1;
+ // move strings and update pointers in Dirs
+ lo = (char*)&b->d[b->md];
+ newlo = (char*)&d[md];
+ hi = b->str;
+ memmove(newlo, lo+((char*)d-(char*)b->d), hi-lo);
+ for(i=0; i<b->nd; i++) {
+ if(lo <= d[i].name && d[i].name < hi)
+ d[i].name += newlo - lo;
+ if(lo <= d[i].uid && d[i].uid < hi)
+ d[i].uid += newlo - lo;
+ if(lo <= d[i].gid && d[i].gid < hi)
+ d[i].gid += newlo - lo;
+ if(lo <= d[i].muid && d[i].muid < hi)
+ d[i].muid += newlo - lo;
+ }
+ b->d = d;
+ b->md = md;
+ b->str += newlo - lo;
+ b->estr = newlo + mstr;
+ }
+ _p9dir(lst, st, name, &b->d[b->nd], &b->str, b->estr);
+ b->nd++;
+ return 0;
+}
+
+static long
+dirreadmax(int fd, Dir **dp, int max)
+{
+ int i;
+ DIR *dir;
+ DirBuild b;
+ struct dirent *de;
+ struct stat st, lst;
+
+ if((dir = dirget(fd)) == nil) {
+ werrstr("not a directory");
+ return -1;
+ }
+
+ memset(&b, 0, sizeof b);
+ for(i=0; max == -1 || i<max; i++) { // max = not too many, not too few
+ errno = 0;
+ de = readdir(dir);
+ if(de == nil) {
+ if(b.nd == 0 && errno != 0)
+ return -1;
+ break;
+ }
+ // Note: not all systems have d_namlen. Assume NUL-terminated.
+ if(de->d_name[0]=='.' && de->d_name[1]==0)
+ continue;
+ if(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0)
+ continue;
+ if(fstatat(fd, de->d_name, &lst, AT_SYMLINK_NOFOLLOW) < 0)
+ continue;
+ st = lst;
+ if(S_ISLNK(lst.st_mode))
+ fstatat(fd, de->d_name, &st, 0);
+ dirbuild1(&b, &lst, &st, de->d_name);
+ }
+ *dp = b.d;
+ return b.nd;
+}
+
+long
+dirread(int fd, Dir **dp)
+{
+ return dirreadmax(fd, dp, 10);
+}
+
+long
+dirreadall(int fd, Dir **dp)
+{
+ return dirreadmax(fd, dp, -1);
+}
diff --git a/src/lib9/readcons.c b/src/lib9/readcons.c
index 8de44b8f..c07e5971 100644
--- a/src/lib9/readcons.c
+++ b/src/lib9/readcons.c
@@ -2,7 +2,9 @@
#define NOPLAN9DEFINES
#include <libc.h>
#include <termios.h>
+#ifdef HAS_SYS_TERMIOS
#include <sys/termios.h>
+#endif
static int
rawx(int fd, int echoing)
diff --git a/src/lib9/seek.c b/src/lib9/seek.c
deleted file mode 100644
index b626355f..00000000
--- a/src/lib9/seek.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-vlong
-seek(int fd, vlong offset, int whence)
-{
- return lseek(fd, offset, whence);
-}
diff --git a/src/libdiskfs/ext2.h b/src/libdiskfs/ext2.h
index f4c32ce3..bf98a9ac 100644
--- a/src/libdiskfs/ext2.h
+++ b/src/libdiskfs/ext2.h
@@ -27,6 +27,39 @@ enum
NAMELEN = 255,
+ /* some systems have these defined */
+ #undef IEXEC
+ #undef IWRITE
+ #undef IREAD
+ #undef ISVTX
+ #undef ISGID
+ #undef ISUID
+ #undef IFMT
+ #undef IFIFO
+ #undef IFCHR
+ #undef IFDIR
+ #undef IFBLK
+ #undef IFREG
+ #undef IFLNK
+ #undef IFSOCK
+ #undef IFWHT
+
+ #define IEXEC EXT2_IEXEC
+ #define IWRITE EXT2_IWRITE
+ #define IREAD EXT2_IREAD
+ #define ISVTX EXT2_ISVTX
+ #define ISGID EXT2_ISGID
+ #define ISUID EXT2_ISUID
+ #define IFMT EXT2_IFMT
+ #define IFIFO EXT2_IFIFO
+ #define IFCHR EXT2_IFCHR
+ #define IFDIR EXT2_IFDIR
+ #define IFBLK EXT2_IFBLK
+ #define IFREG EXT2_IFREG
+ #define IFLNK EXT2_IFLNK
+ #define IFSOCK EXT2_IFSOCK
+ #define IFWHT EXT2_IFWHT
+
/* permissions in Inode.mode */
IEXEC = 00100,
IWRITE = 0200,
diff --git a/src/libdiskfs/ffs.h b/src/libdiskfs/ffs.h
index d7881f15..b8675448 100644
--- a/src/libdiskfs/ffs.h
+++ b/src/libdiskfs/ffs.h
@@ -72,6 +72,39 @@ enum
NDADDR = 12,
NIADDR = 3,
+ /* some systems have these defined */
+ #undef IEXEC
+ #undef IWRITE
+ #undef IREAD
+ #undef ISVTX
+ #undef ISGID
+ #undef ISUID
+ #undef IFMT
+ #undef IFIFO
+ #undef IFCHR
+ #undef IFDIR
+ #undef IFBLK
+ #undef IFREG
+ #undef IFLNK
+ #undef IFSOCK
+ #undef IFWHT
+
+ #define IEXEC FFS_IEXEC
+ #define IWRITE FFS_IWRITE
+ #define IREAD FFS_IREAD
+ #define ISVTX FFS_ISVTX
+ #define ISGID FFS_ISGID
+ #define ISUID FFS_ISUID
+ #define IFMT FFS_IFMT
+ #define IFIFO FFS_IFIFO
+ #define IFCHR FFS_IFCHR
+ #define IFDIR FFS_IFDIR
+ #define IFBLK FFS_IFBLK
+ #define IFREG FFS_IFREG
+ #define IFLNK FFS_IFLNK
+ #define IFSOCK FFS_IFSOCK
+ #define IFWHT FFS_IFWHT
+
/* permissions in Inode.mode */
IEXEC = 00100,
IWRITE = 0200,
diff --git a/src/libdraw/drawclient.c b/src/libdraw/drawclient.c
index 9376f9c0..c38f4801 100644
--- a/src/libdraw/drawclient.c
+++ b/src/libdraw/drawclient.c
@@ -333,7 +333,7 @@ _displayrdkbd(Display *d, Rune *r)
{
Wsysmsg tx, rx;
- tx.type = Trdkbd;
+ tx.type = Trdkbd4;
if(displayrpc(d, &tx, &rx, nil) < 0)
return -1;
*r = rx.rune;
diff --git a/src/libdraw/drawfcall.c b/src/libdraw/drawfcall.c
index eea14095..94115384 100644
--- a/src/libdraw/drawfcall.c
+++ b/src/libdraw/drawfcall.c
@@ -50,6 +50,7 @@ sizeW2M(Wsysmsg *m)
case Rcursor:
case Rcursor2:
case Trdkbd:
+ case Trdkbd4:
case Rlabel:
case Rctxt:
case Rinit:
@@ -73,6 +74,8 @@ sizeW2M(Wsysmsg *m)
return 4+1+1+_stringsize(m->error);
case Rrdkbd:
return 4+1+1+2;
+ case Rrdkbd4:
+ return 4+1+1+4;
case Tlabel:
return 4+1+1+_stringsize(m->label);
case Tctxt:
@@ -117,6 +120,7 @@ convW2M(Wsysmsg *m, uchar *p, uint n)
case Rcursor:
case Rcursor2:
case Trdkbd:
+ case Trdkbd4:
case Rlabel:
case Rctxt:
case Rinit:
@@ -166,6 +170,9 @@ convW2M(Wsysmsg *m, uchar *p, uint n)
case Rrdkbd:
PUT2(p+6, m->rune);
break;
+ case Rrdkbd4:
+ PUT(p+6, m->rune);
+ break;
case Tlabel:
PUTSTRING(p+6, m->label);
break;
@@ -221,6 +228,7 @@ convM2W(uchar *p, uint n, Wsysmsg *m)
case Rcursor:
case Rcursor2:
case Trdkbd:
+ case Trdkbd4:
case Rlabel:
case Rctxt:
case Rinit:
@@ -270,6 +278,9 @@ convM2W(uchar *p, uint n, Wsysmsg *m)
case Rrdkbd:
GET2(p+6, m->rune);
break;
+ case Rrdkbd4:
+ GET(p+6, m->rune);
+ break;
case Tlabel:
GETSTRING(p+6, &m->label);
break;
@@ -360,6 +371,10 @@ drawfcallfmt(Fmt *fmt)
return fmtprint(fmt, "Trdkbd");
case Rrdkbd:
return fmtprint(fmt, "Rrdkbd rune=%C", m->rune);
+ case Trdkbd4:
+ return fmtprint(fmt, "Trdkbd4");
+ case Rrdkbd4:
+ return fmtprint(fmt, "Rrdkbd4 rune=%C", m->rune);
case Tlabel:
return fmtprint(fmt, "Tlabel label='%s'", m->label);
case Rlabel:
diff --git a/src/libdraw/event.c b/src/libdraw/event.c
index 9d7e10c2..e2d5f707 100644
--- a/src/libdraw/event.c
+++ b/src/libdraw/event.c
@@ -284,7 +284,7 @@ extract(int canblock)
}
}else if(i == Skeyboard){
if(eslave[i].rpc == nil)
- eslave[i].rpc = startrpc(Trdkbd);
+ eslave[i].rpc = startrpc(Trdkbd4);
if(eslave[i].rpc){
/* if ready, don't block in select */
if(eslave[i].rpc->p)
diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c
index 9312eb43..8714a8c7 100644
--- a/src/libdraw/openfont.c
+++ b/src/libdraw/openfont.c
@@ -69,7 +69,7 @@ openfont1(Display *d, char *name)
n = _drawflength(fd);
if(fd < 0 && strncmp(fname, "/mnt/font/", 10) == 0) {
fd = _fontpipe(fname+10);
- n = 128*1024;
+ n = 1024*1024;
}
if(fd < 0){
free(nambuf);
diff --git a/src/libip/AIX.c b/src/libip/AIX.c
new file mode 100644
index 00000000..48c87c62
--- /dev/null
+++ b/src/libip/AIX.c
@@ -0,0 +1 @@
+#include "none.c"
diff --git a/src/libmach/AIX.c b/src/libmach/AIX.c
new file mode 100644
index 00000000..3626e7c6
--- /dev/null
+++ b/src/libmach/AIX.c
@@ -0,0 +1 @@
+#include "nosys.c"
diff --git a/src/libthread/Darwin-x86_64-asm.s b/src/libthread/Darwin-x86_64-asm.s
deleted file mode 100644
index d50d3b6d..00000000
--- a/src/libthread/Darwin-x86_64-asm.s
+++ /dev/null
@@ -1,44 +0,0 @@
-.text
-.align 8
-
-.globl _libthread_getmcontext
-_libthread_getmcontext:
- movq $1, 0*8(%rdi) // rax
- movq %rbx, 1*8(%rdi)
- movq %rcx, 2*8(%rdi)
- movq %rdx, 3*8(%rdi)
- movq %rsi, 4*8(%rdi)
- movq %rdi, 5*8(%rdi)
- movq %rbp, 6*8(%rdi)
- movq %rsp, 7*8(%rdi)
- movq %r8, 8*8(%rdi)
- movq %r9, 9*8(%rdi)
- movq %r10, 10*8(%rdi)
- movq %r11, 11*8(%rdi)
- movq %r12, 12*8(%rdi)
- movq %r13, 13*8(%rdi)
- movq %r14, 14*8(%rdi)
- movq %r15, 15*8(%rdi)
- movq $0, %rax
- ret
-
-.globl _libthread_setmcontext
-_libthread_setmcontext:
- movq 0*8(%rdi), %rax
- movq 1*8(%rdi), %rbx
- movq 2*8(%rdi), %rcx
- movq 3*8(%rdi), %rdx
- movq 4*8(%rdi), %rsi
- // %rdi later
- movq 6*8(%rdi), %rbp
- movq 7*8(%rdi), %rsp
- movq 8*8(%rdi), %r8
- movq 9*8(%rdi), %r9
- movq 10*8(%rdi), %r10
- movq 11*8(%rdi), %r11
- movq 12*8(%rdi), %r12
- movq 13*8(%rdi), %r13
- movq 14*8(%rdi), %r14
- movq 15*8(%rdi), %r15
- movq 5*8(%rdi), %rdi
- ret
diff --git a/src/libthread/channel.c b/src/libthread/channel.c
index 53af86e6..9efb7a62 100644
--- a/src/libthread/channel.c
+++ b/src/libthread/channel.c
@@ -141,7 +141,7 @@ altdequeue(Alt *a)
delarray(ar, i);
return;
}
- fprint(2, "cannot find self in altdq\n");
+ fprint(2, "cannot find self in altdequeue\n");
abort();
}
diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c
index 46bb396a..35f6ffe3 100644
--- a/src/libthread/pthread.c
+++ b/src/libthread/pthread.c
@@ -50,13 +50,15 @@ _threadunlock(Lock *lk, ulong pc)
abort();
}
+/* note: _procsleep can have spurious wakeups, like pthread_cond_wait */
void
_procsleep(_Procrendez *r)
{
/* r is protected by r->l, which we hold */
pthread_cond_init(&r->cond, 0);
r->asleep = 1;
- pthread_cond_wait(&r->cond, &r->l->mutex);
+ if(pthread_cond_wait(&r->cond, &r->l->mutex) != 0)
+ sysfatal("pthread_cond_wait: %r");
pthread_cond_destroy(&r->cond);
r->asleep = 0;
}
@@ -99,6 +101,23 @@ startprocfn(void *v)
pthread_exit(0);
}
+static void
+startpthreadfn(void *v)
+{
+ void **a;
+ Proc *p;
+ _Thread *t;
+
+ a = (void**)v;
+ p = a[0];
+ t = a[1];
+ free(a);
+ t->osprocid = pthread_self();
+ pthread_detach(t->osprocid);
+ _threadpthreadmain(p, t);
+ pthread_exit(0);
+}
+
void
_procstart(Proc *p, void (*fn)(Proc*))
{
@@ -116,6 +135,22 @@ _procstart(Proc *p, void (*fn)(Proc*))
}
}
+void
+_threadpthreadstart(Proc *p, _Thread *t)
+{
+ void **a;
+
+ a = malloc(3*sizeof a[0]);
+ if(a == nil)
+ sysfatal("_pthreadstart malloc: %r");
+ a[0] = p;
+ a[1] = t;
+ if(pthread_create(&t->osprocid, nil, (void*(*)(void*))startpthreadfn, (void*)a) < 0){
+ fprint(2, "pthread_create: %r\n");
+ abort();
+ }
+}
+
static pthread_key_t prockey;
Proc*
diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh
index 20811cdf..833afbe0 100644
--- a/src/libthread/sysofiles.sh
+++ b/src/libthread/sysofiles.sh
@@ -15,14 +15,14 @@ esac
# Various libc don't supply swapcontext, makecontext, so we do.
case "$SYSNAME-$OBJTYPE" in
-Darwin-x86_64 | Linux-arm | Linux-sparc64 | NetBSD-arm | OpenBSD-386 | OpenBSD-power | OpenBSD-x86_64)
+Linux-arm | Linux-sparc64 | NetBSD-arm | OpenBSD-386 | OpenBSD-power | OpenBSD-x86_64)
echo $OBJTYPE-ucontext.o
;;
esac
# A few libc don't supply setcontext, getcontext, so we do.
case "$SYSNAME-$OBJTYPE" in
-Darwin-x86_64 | Linux-arm | Linux-sparc64 | OpenBSD-386 | OpenBSD-power | OpenBSD-x86_64)
+Linux-arm | Linux-sparc64 | OpenBSD-386 | OpenBSD-power | OpenBSD-x86_64)
echo $SYSNAME-$OBJTYPE-asm.o
;;
esac
diff --git a/src/libthread/thread.c b/src/libthread/thread.c
index f657b5b2..902942d9 100644
--- a/src/libthread/thread.c
+++ b/src/libthread/thread.c
@@ -7,6 +7,7 @@ static uint threadnsysproc;
static Lock threadnproclock;
static Ref threadidref;
static Proc *threadmainproc;
+static int pthreadperthread;
static void addproc(Proc*);
static void delproc(Proc*);
@@ -53,9 +54,9 @@ _threaddebug(char *fmt, ...)
va_end(arg);
t = proc()->thread;
if(t)
- fprint(fd, "%d.%d: %s\n", getpid(), t->id, buf);
+ fprint(fd, "%p %d.%d: %s\n", proc(), getpid(), t->id, buf);
else
- fprint(fd, "%d._: %s\n", getpid(), buf);
+ fprint(fd, "%p %d._: %s\n", proc(), getpid(), buf);
}
static _Thread*
@@ -176,12 +177,16 @@ _threadcreate(Proc *p, void (*fn)(void*), void *arg, uint stack)
if(stack < (256<<10))
stack = 256<<10;
- if(p->nthread == 0)
+ if(p->nthread == 0 || pthreadperthread)
stack = 0; // not using it
t = threadalloc(fn, arg, stack);
t->proc = p;
- addthreadinproc(p, t);
+ if(p->nthread == 0)
+ p->thread0 = t;
+ else if(pthreadperthread)
+ _threadpthreadstart(p, t);
p->nthread++;
+ addthreadinproc(p, t);
_threadready(t);
return t;
}
@@ -209,6 +214,37 @@ proccreate(void (*fn)(void*), void *arg, uint stack)
return id;
}
+// For pthreadperthread mode, procswitch flips
+// between the threads.
+static void
+procswitch(Proc *p, _Thread *from, _Thread *to)
+{
+ _threaddebug("procswitch %p %d %d", p, from?from->id:-1, to?to->id:-1);
+ lock(&p->schedlock);
+ from->schedrend.l = &p->schedlock;
+ if(to) {
+ p->schedthread = to;
+ to->schedrend.l = &p->schedlock;
+ _threaddebug("procswitch wakeup %p %d", p, to->id);
+ _procwakeup(&to->schedrend);
+ }
+ if(p->schedthread != from) {
+ if(from->exiting) {
+ unlock(&p->schedlock);
+ _threadpexit();
+ _threaddebug("procswitch exit wakeup!!!\n");
+ }
+ while(p->schedthread != from) {
+ _threaddebug("procswitch sleep %p %d", p, from->id);
+ _procsleep(&from->schedrend);
+ _threaddebug("procswitch awake %p %d", p, from->id);
+ }
+ if(p->schedthread != from)
+ sysfatal("_procswitch %p %p oops", p->schedthread, from);
+ }
+ unlock(&p->schedlock);
+}
+
void
_threadswitch(void)
{
@@ -216,9 +252,13 @@ _threadswitch(void)
needstack(0);
p = proc();
+
/*print("threadswtch %p\n", p); */
- if(p->thread->stk == nil)
+
+ if(p->thread == p->thread0)
procscheduler(p);
+ else if(pthreadperthread)
+ procswitch(p, p->thread, p->thread0);
else
contextswitch(&p->thread->context, &p->schedcontext);
}
@@ -346,6 +386,15 @@ procmain(Proc *p)
threadexits(nil);
}
+void
+_threadpthreadmain(Proc *p, _Thread *t)
+{
+ _threadsetproc(p);
+ procswitch(p, t, nil);
+ t->startfn(t->startarg);
+ threadexits(nil);
+}
+
static void
procscheduler(Proc *p)
{
@@ -401,9 +450,13 @@ Top:
p->nswitch++;
_threaddebug("run %d (%s)", t->id, t->name);
//print("run %p %p %p %p\n", t, *(uintptr*)(t->context.uc.mc.sp), t->context.uc.mc.di, t->context.uc.mc.si);
- if(t->stk == nil)
+ if(t == p->thread0)
return;
- contextswitch(&p->schedcontext, &t->context);
+ if(pthreadperthread)
+ procswitch(p, p->thread0, t);
+ else
+ contextswitch(&p->schedcontext, &t->context);
+ _threaddebug("back in scheduler");
/*print("back in scheduler\n"); */
goto Top;
}
@@ -545,6 +598,10 @@ threadqlock(QLock *l, int block, ulong pc)
if(l->owner == nil){
l->owner = (*threadnow)();
/*print("qlock %p @%#x by %p\n", l, pc, l->owner); */
+ if(l->owner == nil) {
+ fprint(2, "%s: qlock uncontended owner=nil oops\n", argv0);
+ abort();
+ }
unlock(&l->l);
return 1;
}
@@ -569,6 +626,11 @@ threadqlock(QLock *l, int block, ulong pc)
argv0, pc, l->owner, (*threadnow)());
abort();
}
+ if(l->owner == nil) {
+ fprint(2, "%s: qlock threadswitch owner=nil oops\n", argv0);
+ abort();
+ }
+
/*print("qlock wakeup %p @%#x by %p\n", l, pc, (*threadnow)()); */
return 1;
}
@@ -757,10 +819,24 @@ int
main(int argc, char **argv)
{
Proc *p;
+ char *opts;
argv0 = argv[0];
- if(getenv("NOLIBTHREADDAEMONIZE") == nil)
+ opts = getenv("LIBTHREAD");
+ if(opts == nil)
+ opts = "";
+
+ pthreadperthread = (strstr(opts, "pthreadperthread") != nil);
+#ifdef PLAN9PORT_ASAN
+ // ASAN can't deal with the coroutine stack switches.
+ // In theory it has support for informing it about stack switches,
+ // but even with those calls added it can't deal with things
+ // like fork or exit from a coroutine stack.
+ // Easier to just run in pthread-per-thread mode.
+ pthreadperthread = 1;
+#endif
+ if(strstr(opts, "nodaemon") == nil && getenv("NOLIBTHREADDAEMONIZE") == nil)
_threadsetupdaemonize();
threadargc = argc;
diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
index cceb1b8e..8d22a161 100644
--- a/src/libthread/threadimpl.h
+++ b/src/libthread/threadimpl.h
@@ -7,7 +7,7 @@
#include <signal.h>
#if !defined(__OpenBSD__)
# if defined(__APPLE__)
-# define _XOPEN_SOURCE /* for Snow Leopard */
+# define _XOPEN_SOURCE /* for Snow Leopard */
# endif
# include <ucontext.h>
#endif
@@ -15,31 +15,6 @@
#include "libc.h"
#include "thread.h"
-#if defined(__APPLE__)
- /*
- * OS X before 10.5 (Leopard) does not provide
- * swapcontext nor makecontext, so we have to use our own.
- * In theory, Leopard does provide them, but when we use
- * them, they seg fault. Maybe we're using them wrong.
- * So just use our own versions, even on Leopard.
- */
-# define mcontext libthread_mcontext
-# define mcontext_t libthread_mcontext_t
-# define ucontext libthread_ucontext
-# define ucontext_t libthread_ucontext_t
-# define swapcontext libthread_swapcontext
-# define makecontext libthread_makecontext
-# if defined(__i386__)
-# include "386-ucontext.h"
-# elif defined(__x86_64__)
-# include "x86_64-ucontext.h"
-# elif defined(__ppc__) || defined(__power__)
-# include "power-ucontext.h"
-# else
-# error "unknown architecture"
-# endif
-#endif
-
#if defined(__OpenBSD__)
# define mcontext libthread_mcontext
# define mcontext_t libthread_mcontext_t
@@ -82,15 +57,6 @@ enum
struct Context
{
ucontext_t uc;
-#ifdef __APPLE__
- /*
- * On Snow Leopard, etc., the context routines exist,
- * so we use them, but apparently they write past the
- * end of the ucontext_t. Sigh. We put some extra
- * scratch space here for them.
- */
- uchar buf[1024];
-#endif
};
struct Execjob
@@ -102,6 +68,17 @@ struct Execjob
Channel *c;
};
+struct _Procrendez
+{
+ Lock *l;
+ int asleep;
+#ifdef PLAN9PORT_USING_PTHREADS
+ pthread_cond_t cond;
+#else
+ int pid;
+#endif
+};
+
struct _Thread
{
_Thread *next;
@@ -112,6 +89,11 @@ struct _Thread
void (*startfn)(void*);
void *startarg;
uint id;
+#ifdef PLAN9PORT_USING_PTHREADS
+ pthread_t osprocid;
+#else
+ int osprocid;
+#endif
uchar *stk;
uint stksize;
int exiting;
@@ -120,17 +102,7 @@ struct _Thread
char state[256];
void *udata;
Alt *alt;
-};
-
-struct _Procrendez
-{
- Lock *l;
- int asleep;
-#ifdef PLAN9PORT_USING_PTHREADS
- pthread_cond_t cond;
-#else
- int pid;
-#endif
+ _Procrendez schedrend;
};
extern void _procsleep(_Procrendez*);
@@ -149,6 +121,7 @@ struct Proc
#endif
Lock lock;
int nswitch;
+ _Thread *thread0;
_Thread *thread;
_Thread *pinthread;
_Threadlist runqueue;
@@ -157,6 +130,8 @@ struct Proc
uint nthread;
uint sysproc;
_Procrendez runrend;
+ Lock schedlock;
+ _Thread *schedthread;
Context schedcontext;
void *udata;
Jmp sigjmp;
@@ -188,6 +163,8 @@ extern void _threadpexit(void);
extern void _threaddaemonize(void);
extern void *_threadstkalloc(int);
extern void _threadstkfree(void*, int);
+extern void _threadpthreadmain(Proc*, _Thread*);
+extern void _threadpthreadstart(Proc*, _Thread*);
#define USPALIGN(ucp, align) \
(void*)((((uintptr)(ucp)->uc_stack.ss_sp+(ucp)->uc_stack.ss_size)-(align))&~((align)-1))
diff --git a/src/mkenv b/src/mkenv
index 6ff746e0..6c89f141 100644
--- a/src/mkenv
+++ b/src/mkenv
@@ -20,3 +20,4 @@ OBJTYPE=`(uname -m -p 2>/dev/null || uname -m) | sed '
s;.*aarch64.*;arm64;
s;.*arm64.*;arm64;
'`
+INSTALL=`[ $(uname) = AIX ] && echo installbsd || echo install`
diff --git a/src/mkfile b/src/mkfile
index 8ddaee20..4740780d 100644
--- a/src/mkfile
+++ b/src/mkfile
@@ -30,11 +30,12 @@ mkmk.sh:VD:
(cd lib9; mk -n -a install)
echo cd ..
for i in libbio libregexp cmd/mk
- do
+ do
(cd $i; echo cd $i; echo 'echo cd `pwd`'; mk -n -a install)
echo cd ..
done
) | sed '
+ s/'$INSTALL'/$INSTALL/g
s/'$SYSNAME'/$SYSNAME/g
s/'$OBJTYPE'/$OBJTYPE/g
s;'$PLAN9';$PLAN9;g
diff --git a/src/mkhdr b/src/mkhdr
index 24889cde..35a2ccc5 100644
--- a/src/mkhdr
+++ b/src/mkhdr
@@ -11,7 +11,6 @@ CC=9c
LD=9l
AS=9a
AR=9ar
-INSTALL=install
CFLAGS=
LDFLAGS=
AFLAGS=
@@ -24,5 +23,3 @@ LIB=
SHORTLIB=9
<|cat $PLAN9/config 2>/dev/null || true
-<|cat $PLAN9/src/mk.$SYSNAME-$OBJTYPE 2>/dev/null || true
-
diff --git a/src/mkmk.sh b/src/mkmk.sh
index dae87ddf..dfccd369 100644
--- a/src/mkmk.sh
+++ b/src/mkmk.sh
@@ -20,14 +20,12 @@ echo cd `pwd`
9c convM2D.c
9c convM2S.c
9c convS2M.c
-9c create.c
9c crypt.c
9c ctime.c
9c dial.c
9c dirfstat.c
9c dirfwstat.c
9c dirmodefmt.c
-9c dirread.c
9c dirstat.c
9c dirwstat.c
9c dup.c
@@ -75,7 +73,6 @@ echo cd `pwd`
9c readn.c
9c rfork.c
9c searchpath.c
-9c seek.c
9c sendfd.c
9c sleep.c
9c strdup.c
@@ -109,6 +106,7 @@ echo cd `pwd`
9c -Ifmt fmt/fmtstr.c
9c -Ifmt fmt/fmtvprint.c
9c -Ifmt fmt/fprint.c
+9c frexp.c
9c -Ifmt fmt/nan64.c
9c -Ifmt fmt/print.c
9c -Ifmt fmt/runefmtstr.c
@@ -150,7 +148,7 @@ echo cd `pwd`
9c utf/utfrrune.c
9c utf/utfrune.c
9c utf/utfutf.c
-9ar rsc $PLAN9/lib/lib9.a _exits.o _p9dialparse.o _p9dir.o announce.o argv0.o atexit.o atoi.o atol.o atoll.o atnotify.o await.o cistrcmp.o cistrncmp.o cistrstr.o cleanname.o convD2M.o convM2D.o convM2S.o convS2M.o create.o crypt.o ctime.o dial.o dirfstat.o dirfwstat.o dirmodefmt.o dirread.o dirstat.o dirwstat.o dup.o encodefmt.o errstr.o exec.o execl.o exitcode.o fcallfmt.o frand.o get9root.o getcallerpc.o getenv.o getfields.o getnetconn.o getns.o getuser.o getwd.o jmp.o lrand.o lnrand.o main.o malloc.o malloctag.o mallocz.o nan.o needsrcquote.o needstack.o netcrypt.o netmkaddr.o notify.o nrand.o nulldir.o open.o opentemp.o pin.o pipe.o post9p.o postnote.o qlock.o quote.o rand.o read9pmsg.o readcons.o readn.o rfork.o searchpath.o seek.o sendfd.o sleep.o strdup.o strecpy.o sysfatal.o syslog.o sysname.o time.o tm2sec.o tokenize.o truerand.o u16.o u32.o u64.o unsharp.o wait.o waitpid.o write.o zoneinfo.o dofmt.o fltfmt.o fmt.o fmtfd.o fmtfdflush.o fmtlocale.o fmtlock2.o fmtnull.o fmtprint.o fmtquote.o fmtrune.o fmtstr.o fmtvprint.o fprint.o nan64.o print.o runefmtstr.o runeseprint.o runesmprint.o runesnprint.o runesprint.o runevseprint.o runevsmprint.o runevsnprint.o seprint.o smprint.o snprint.o sprint.o strtod.o vfprint.o vseprint.o vsmprint.o vsnprint.o charstod.o pow10.o rune.o runestrcat.o runestrchr.o runestrcmp.o runestrcpy.o runestrdup.o runestrlen.o runestrecpy.o runestrncat.o runestrncmp.o runestrncpy.o runestrrchr.o runestrstr.o runetype.o utfecpy.o utflen.o utfnlen.o utfrrune.o utfrune.o utfutf.o
+9ar rsc $PLAN9/lib/lib9.a _exits.o _p9dialparse.o _p9dir.o announce.o argv0.o atexit.o atoi.o atol.o atoll.o atnotify.o await.o cistrcmp.o cistrncmp.o cistrstr.o cleanname.o convD2M.o convM2D.o convM2S.o convS2M.o crypt.o ctime.o dial.o dirfstat.o dirfwstat.o dirmodefmt.o dirstat.o dirwstat.o dup.o encodefmt.o errstr.o exec.o execl.o exitcode.o fcallfmt.o frand.o get9root.o getcallerpc.o getenv.o getfields.o getnetconn.o getns.o getuser.o getwd.o jmp.o lrand.o lnrand.o main.o malloc.o malloctag.o mallocz.o nan.o needsrcquote.o needstack.o netcrypt.o netmkaddr.o notify.o nrand.o nulldir.o open.o opentemp.o pin.o pipe.o post9p.o postnote.o qlock.o quote.o rand.o read9pmsg.o readcons.o readn.o rfork.o searchpath.o sendfd.o sleep.o strdup.o strecpy.o sysfatal.o syslog.o sysname.o time.o tm2sec.o tokenize.o truerand.o u16.o u32.o u64.o unsharp.o wait.o waitpid.o write.o zoneinfo.o dofmt.o fltfmt.o fmt.o fmtfd.o fmtfdflush.o fmtlocale.o fmtlock2.o fmtnull.o fmtprint.o fmtquote.o fmtrune.o fmtstr.o fmtvprint.o fprint.o frexp.o nan64.o print.o runefmtstr.o runeseprint.o runesmprint.o runesnprint.o runesprint.o runevseprint.o runevsmprint.o runevsnprint.o seprint.o smprint.o snprint.o sprint.o strtod.o vfprint.o vseprint.o vsmprint.o vsnprint.o charstod.o pow10.o rune.o runestrcat.o runestrchr.o runestrcmp.o runestrcpy.o runestrdup.o runestrlen.o runestrecpy.o runestrncat.o runestrncmp.o runestrncpy.o runestrrchr.o runestrstr.o runetype.o utfecpy.o utflen.o utfnlen.o utfrrune.o utfrune.o utfutf.o
cd ..
cd libbio
echo cd `pwd`
@@ -211,5 +209,5 @@ echo cd `pwd`
9c word.c
9c unix.c
9l -o o.mk arc.o archive.o bufblock.o env.o file.o graph.o job.o lex.o main.o match.o mk.o parse.o recipe.o rc.o rule.o run.o sh.o shell.o shprint.o symtab.o var.o varsub.o word.o unix.o
-install o.mk $PLAN9/bin/mk
+$INSTALL o.mk $PLAN9/bin/mk
cd ..