diff options
author | Mystery Man <unknown@mandriva.org> | 2001-05-14 14:17:54 +0000 |
---|---|---|
committer | Mystery Man <unknown@mandriva.org> | 2001-05-14 14:17:54 +0000 |
commit | 16984701aa5165b77f229cc318e8025ee8cf81b5 (patch) | |
tree | 923ed2780582f751b2be106641be35cf71fedd66 | |
parent | c5050eb3ba91cf0eab748b773dcbb34b88ae88bc (diff) | |
download | drakx-topic/dietlibc.tar drakx-topic/dietlibc.tar.gz drakx-topic/dietlibc.tar.bz2 drakx-topic/dietlibc.tar.xz drakx-topic/dietlibc.zip |
This commit was manufactured by cvs2svn to create branch 'dietlibc'.topic/dietlibc
81 files changed, 2876 insertions, 0 deletions
diff --git a/mdk-stage1/dietlibc/libcrypt/crypt.c b/mdk-stage1/dietlibc/libcrypt/crypt.c new file mode 100644 index 000000000..933397f5f --- /dev/null +++ b/mdk-stage1/dietlibc/libcrypt/crypt.c @@ -0,0 +1,309 @@ +#include "dietfeatures.h" +#include <unistd.h> + +/* Initial permutation, */ +static char IP[] = { + 57,49,41,33,25,17, 9, 1, + 59,51,43,35,27,19,11, 3, + 61,53,45,37,29,21,13, 5, + 63,55,47,39,31,23,15, 7, + 56,48,40,32,24,16, 8, 0, + 58,50,42,34,26,18,10, 2, + 60,52,44,36,28,20,12, 4, + 62,54,46,38,30,22,14, 6 +}; + +/* Final permutation, FP = IP^(-1) */ +static char FP[] = { + 39, 7,47,15,55,23,63,31, + 38, 6,46,14,54,22,62,30, + 37, 5,45,13,53,21,61,29, + 36, 4,44,12,52,20,60,28, + 35, 3,43,11,51,19,59,27, + 34, 2,42,10,50,18,58,26, + 33, 1,41, 9,49,17,57,25, + 32, 0,40, 8,48,16,56,24 +}; + +/* Permuted-choice 1 from the key bits to yield C and D. + * Note that bits 8,16... are left out: They are intended for a parity check. + */ +static char PC1_C[] = { + 56,48,40,32,24,16, 8, + 0,57,49,41,33,25,17, + 9, 1,58,50,42,34,26, + 18,10, 2,59,51,43,35 +}; + +static char PC1_D[] = { + 62,54,46,38,30,22,14, + 6,61,53,45,37,29,21, + 13, 5,60,52,44,36,28, + 20,12, 4,27,19,11, 3 +}; + +/* Sequence of shifts used for the key schedule. */ +static char shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 }; + +/* + * Permuted-choice 2, to pick out the bits from the CD array that generate + * the key schedule. + */ +static char PC2_C[] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1 +}; + +static char PC2_D[] = { + 12, 23, 2, 8, 18, 26, 1, 11, 22, 16, 4, 19, + 15, 20, 10, 27, 5, 24, 17, 13, 21, 7, 0, 3 +}; + +/* The C and D arrays used to calculate the key schedule. */ + +static char C[28]; +static char D[28]; +/* The key schedule. Generated from the key. */ +static char KS[16][48]; + +/* The E bit-selection table. */ +static char E[48]; +static char e2[] = { + 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 +}; + +/* Set up the key schedule from the key. */ +void setkey(const char *key) +{ + register int i, j, k; + int t; + int s; + + /* First, generate C and D by permuting the key. The low order bit of each + * 8-bit char is not used, so C and D are only 28 bits apiece. + */ + for(i=0; i < 28; i++) { + C[i] = key[(int)PC1_C[i]]; + D[i] = key[(int)PC1_D[i]]; + } + /* To generate Ki, rotate C and D according to schedule and pick up a + * permutation using PC2. + */ + for(i=0; i < 16; i++) { + /* rotate. */ + s = shifts[i]; + for(k=0; k < s; k++) { + t = C[0]; + for(j=0; j < 27; j++) + C[j] = C[j+1]; + C[27] = t; + t = D[0]; + for(j=0; j < 27; j++) + D[j] = D[j+1]; + D[27] = t; + } + /* get Ki. Note C and D are concatenated. */ + for(j=0; j < 24; j++) { + KS[i][j] = C[(int)PC2_C[j]]; + KS[i][j+24] = D[(int)PC2_D[j]]; + } + } + + for(i=0; i < 48; i++) + E[i] = e2[i]; +} + +/* The 8 selection functions. For some reason, they give a 0-origin index, + * unlike everything else. + */ +static char S[8][64] = { + { + 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, + 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, + 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, + 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13 + }, + + { + 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, + 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, + 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, + 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9 + }, + + { + 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, + 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, + 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12 + }, + + { + 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, + 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, + 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, + 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14 + }, + + { + 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, + 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, + 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, + 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3 + }, + + { + 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, + 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, + 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, + 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13 + }, + + { + 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, + 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, + 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, + 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12 + }, + + { + 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, + 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, + 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, + 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11 + } +}; + +/* P is a permutation on the selected combination of the current L and key. */ +static char P[] = { + 15, 6,19,20, 28,11,27,16, 0,14,22,25, 4,17,30, 9, + 1, 7,23,13, 31,26, 2, 8, 18,12,29, 5, 21,10, 3,24 +}; + +/* The current block, divided into 2 halves. */ +static char L[32], R[32]; +static char tempL[32]; +static char f[32]; + +/* The combination of the key and the input, before selection. */ +static char preS[48]; + +/* The payoff: encrypt a block. */ +void encrypt(char block[64], int edflag) +{ + int i, ii; + register int t, j, k; + + /* First, permute the bits in the input */ + for(j=0; j < 64; j++) + L[j] = block[(int)IP[j]]; + /* Perform an encryption operation 16 times. */ + for(ii=0; ii < 16; ii++) { + i = ii; + /* Save the R array, which will be the new L. */ + for(j=0; j < 32; j++) + tempL[j] = R[j]; + /* Expand R to 48 bits using the E selector; + * exclusive-or with the current key bits. + */ + for(j=0; j < 48; j++) + preS[j] = R[E[j]-1] ^ KS[i][j]; + /* The pre-select bits are now considered in 8 groups of 6 bits each. + * The 8 selection functions map these 6-bit quantities into 4-bit + * quantities and the results permuted to make an f(R, K). + * The indexing into the selection functions is peculiar; + * it could be simplified by rewriting the tables. + */ + for(j=0; j < 8; j++) { + t = ((j<<1)+j)<<1; + k = S[j][(preS[t]<<5)+ + (preS[t+1]<<3)+ + (preS[t+2]<<2)+ + (preS[t+3]<<1)+ + (preS[t+4] )+ + (preS[t+5]<<4)]; + t = j << 2; + f[t ] = (k>>3)&01; + f[t+1] = (k>>2)&01; + f[t+2] = (k>>1)&01; + f[t+3] = (k )&01; + } + /* The new R is L ^ f(R, K). The f here has to be permuted first, though. */ + for(j=0; j < 32; j++) + R[j] = L[j] ^ f[(int)P[j]]; + /* Finally, the new L (the original R) is copied back. */ + for(j=0; j < 32; j++) + L[j] = tempL[j]; + } + /* The output L and R are reversed. */ + for(j=0; j < 32; j++) { + L[j] ^= R[j]; + R[j] ^= L[j]; + L[j] ^= R[j]; + } + /* The final output gets the inverse permutation of the very original. */ + for(j=0; j < 64; j++) + block[j] = L[(int)FP[j]]; +} + +char * crypt(const char *pw, const char *salt) +{ + register int i, j, c; + static char block[66], iobuf[16]; + + for(i=0; i < 66; i++) + block[i] = 0; + for(i=0; (c= *pw) && i < 64; pw++) { + for(j=0; j < 7; j++, i++) + block[i] = (c>>(6-j)) & 01; + i++; + } + + setkey(block); + + for(i=0; i < 66; i++) + block[i] = 0; + + for(i=0; i < 2; i++) { + c = *salt++; + iobuf[i] = c; + if(c > 'Z') + c -= 6; + if(c > '9') + c -= 7; + c -= '.'; + for(j=0; j < 6; j++) { + if((c>>j) & 01) { + int ind1 = (((i<<1)+i)<< 1) + j; + int ind2 = ind1 + 24; + E[ind1] ^= E[ind2]; + E[ind2] ^= E[ind1]; + E[ind1] ^= E[ind2]; + } + } + } + + for(i=0; i < 25; i++) + encrypt(block, 0); + + for(i=0; i < 11; i++) { + c = 0; + for(j=0; j < 6; j++) { + c <<= 1; + c |= block[(((i<<1)+i)<<1)+j]; + } + c += '.'; + if(c > '9') + c += 7; + if(c > 'Z') + c += 6; + iobuf[i+2] = c; + } + iobuf[i+2] = 0; + if(iobuf[1] == 0) + iobuf[1] = iobuf[0]; + return(iobuf); +} diff --git a/mdk-stage1/dietlibc/libdl/Makefile b/mdk-stage1/dietlibc/libdl/Makefile new file mode 100644 index 000000000..c0463f887 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/Makefile @@ -0,0 +1,24 @@ +# local "test" make file + +SRC = $(wildcard *.c) test/test.c +OBJ = _dl_jump.o $(SRC:.c=.o) + +#CFLAGS = -Wall -O2 +CFLAGS = -g + +%.o : %.S + $(HOME)/bin/diet gcc $(CFLAGS) -c -o $@ $^ + +%.o : %.c + $(HOME)/bin/diet gcc $(CFLAGS) -c -o $@ $^ + +all: test.out + +test.g: test.c + gcc -o $@ $^ -ldl + +test.out: $(OBJ) + $(HOME)/bin/diet gcc -o $@ $^ + +clean: + $(RM) *.o *.a *.out *~ # *.so diff --git a/mdk-stage1/dietlibc/libdl/README b/mdk-stage1/dietlibc/libdl/README new file mode 100644 index 000000000..5d77bde34 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/README @@ -0,0 +1,6 @@ +this is the experimental libdl test-pre-pre-alpha code + +written by Olaf Dreesen + +Shouldn't work yet had some problems with the elf specs... +and more inconsistencies... diff --git a/mdk-stage1/dietlibc/libdl/_dl_int.h b/mdk-stage1/dietlibc/libdl/_dl_int.h new file mode 100644 index 000000000..659e6ee0f --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/_dl_int.h @@ -0,0 +1,31 @@ +#ifndef ___DL_INT_H__ +#define ___DL_INT_H__ + +#include <elf.h> + +struct _dl_handle { + /* basic */ + void * mem_base; /* base address of maped *.so */ + unsigned long mem_size; /* len of mem block */ + unsigned int lnk_count; /* reference count */ + + /* symbol resolve helper */ + unsigned long*hash_tab; /* hash table */ + Elf32_Sym * dyn_sym_tab; /* dynamic symbol table */ + char * dyn_str_tab; /* dyn_name table */ + + Elf32_Rel * plt_rel; /* PLT relocation table */ + + /* FINI */ + void (*fini)(void); +}; + +#define HASH_BUCKET_LEN(p) ((p)) +#define HASH_BUCKET(p) ((p)+2) + +#define HASH_CHAIN_LEN(p) ((p)+1) +#define HASH_CHAIN(p) ((p)+2+HASH_BUCKET_LEN(p)) + +unsigned long elf_hash(const unsigned char *name); + +#endif diff --git a/mdk-stage1/dietlibc/libdl/_dl_jump.S b/mdk-stage1/dietlibc/libdl/_dl_jump.S new file mode 100644 index 000000000..134f31ea5 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/_dl_jump.S @@ -0,0 +1,8 @@ +.text +.global _dl_jump +_dl_jump: + call do_rel + pop %edx + pop %edx + jmp *%eax + diff --git a/mdk-stage1/dietlibc/libdl/_dl_open.c b/mdk-stage1/dietlibc/libdl/_dl_open.c new file mode 100644 index 000000000..1f907db21 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/_dl_open.c @@ -0,0 +1,207 @@ +#include <stdio.h> +#include <unistd.h> +#include <sys/mman.h> +#include <dlfcn.h> +#include <linux/elf.h> + +#include "_dl_int.h" + +struct _dl_handle dl_test; + +#define _ELF_DWN_ROUND(ps,n) ((n)&(~((ps)-1))) +#define _ELF_UP_ROUND(ps,n) ((((n)&((ps)-1))?(ps):0)+ _ELF_DWN_ROUND((ps),(n))) +#define _ELF_RST_ROUND(ps,n) ((n)&((ps)-1)) + +void _dl_jump(); + +/* + * this file is a Q. & D. hack ... don't think this is bug free or meaningfull + */ + +static void *do_map_in(void *base, unsigned long length, int flags, int fd, unsigned long offset) +{ + int perm = 0; + if (flags & PF_X) perm|=PROT_EXEC; + if (flags & PF_R) perm|=PROT_READ; + if (flags & PF_W) perm|=PROT_WRITE; + return mmap(base, length, perm, MAP_PRIVATE|((base)?MAP_FIXED:0), fd, offset); +} + +unsigned long do_rel(struct _dl_handle * tmp_dl, unsigned long off) +{ +// struct _dl_handle * tmp_dl = ((void*)*((&off)-1)); + Elf32_Rel *tmp = ((void*)tmp_dl->plt_rel)+off; + int sym=ELF32_R_SYM(tmp->r_info); + register unsigned long sym_val; + + printf("do_rel %08x %08x\n",tmp_dl,off); + + printf ("do_rel %08x+%x\n",tmp_dl->plt_rel,off); + printf("do_rel @ %08x with type %d -> %d\n",tmp->r_offset,ELF32_R_TYPE(tmp->r_info),sym); + + printf("do_rel sym %08x\n",tmp_dl->dyn_sym_tab[sym].st_value); + + /* modify GOT for REAL symbol */ + sym_val=((unsigned long)(tmp_dl->mem_base+tmp_dl->dyn_sym_tab[sym].st_value)); + *((unsigned long*)(tmp_dl->mem_base+tmp->r_offset))=sym_val; + + printf("do_rel sym %08x\n",sym_val); + /* HOWTO JUMP ?!? */ + return sym_val; +} + +void *_dl_open(const char*pathname, int fd, int flag) +{ + int ps=getpagesize(); + int i; + unsigned char buf[1024]; + char *m=0,*d; + struct _dl_handle *ret=0; + + unsigned long l; + + Elf32_Ehdr *eh; + Elf32_Phdr *ph; + + int ld_nr=0; + Elf32_Phdr *ld[4]={0,0,0,0}; + Elf32_Phdr *dyn=0; + + if (fd==-1) return 0; + + printf("_dl_open: %s\n",pathname); + + read(fd, buf, 1024); + eh=(Elf32_Ehdr*)buf; + ph=(Elf32_Phdr*)&buf[eh->e_phoff]; + + for (i=0; i<eh->e_phnum; i++) { + if (ph[i].p_type==PT_LOAD) { + ld[ld_nr++]=ph+i; + } + if (ph[i].p_type==PT_DYNAMIC) { + dyn=ph+i; + } + } + + if (ld_nr==1) { + unsigned long offset = _ELF_DWN_ROUND(ps,ld[0]->p_offset); + unsigned long off = _ELF_RST_ROUND(ps,ld[0]->p_offset); + unsigned long length = _ELF_UP_ROUND(ps,ld[0]->p_memsz+off); + m = (char*)do_map_in(0, length, ld[0]->p_flags, fd, offset); + + /* zero pad bss */ + l = ld[0]->p_offset+ld[0]->p_filesz; + memset(m+l,0,length-l); + + dl_test.mem_base=m; + dl_test.mem_size=length; + dl_test.lnk_count=0; + + ret = &dl_test; + } + else if (ld_nr==2) { /* aem... yes Quick & Really Dirty / for the avarage 99% */ + //unsigned long text_addr = _ELF_DWN_ROUND(ps,ld[0]->p_vaddr); + unsigned long text_offset = _ELF_DWN_ROUND(ps,ld[0]->p_offset); + unsigned long text_off = _ELF_RST_ROUND(ps,ld[0]->p_offset); + unsigned long text_size = _ELF_UP_ROUND(ps,ld[0]->p_memsz+text_off); + + unsigned long data_addr = _ELF_DWN_ROUND(ps,ld[1]->p_vaddr); + unsigned long data_offset = _ELF_DWN_ROUND(ps,ld[1]->p_offset); + unsigned long data_off = _ELF_RST_ROUND(ps,ld[1]->p_offset); + unsigned long data_size = _ELF_UP_ROUND(ps,ld[1]->p_memsz+data_off); + unsigned long data_fsize = _ELF_UP_ROUND(ps,ld[1]->p_filesz+data_off); + + /* mmap all mem_blocks for *.so */ + l = text_size+data_size; + + dl_test.mem_size=l; + + m = (char*) do_map_in(0,l,ld[0]->p_flags,fd,text_offset); + + /* release data,bss part */ + mprotect(m+data_addr, data_size, PROT_NONE); + + /* mmap data,bss part */ + d = (char*) do_map_in(m+data_addr,data_fsize,ld[1]->p_flags,fd,data_offset); + + /* zero pad bss */ + l = data_off+ld[1]->p_filesz; + memset(d+l,0,data_size-l); + + /* more bss ? */ + if (data_size>data_fsize) { + l = data_size-data_fsize; + mmap(d+data_fsize, l, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); + } + + dl_test.mem_base=m; + dl_test.lnk_count=0; + ret = &dl_test; + } + + printf("_dl_open pre resolv\n"); + if (ret) { + Elf32_Dyn* dyn_tab = (void*)m+dyn->p_vaddr; + void (*init)(); + unsigned long* got=0; + void* jmprel=0; + int pltreltype=0; + int pltrelsize=0; + + printf("_dl_open IN resolv\n"); + for(i=0;dyn_tab[i].d_tag;i++) { + if (dyn_tab[i].d_tag==DT_HASH) { + ret->hash_tab = (unsigned long*)(m+dyn_tab[i].d_un.d_ptr); + } + if (dyn_tab[i].d_tag==DT_SYMTAB) { + ret->dyn_sym_tab = (Elf32_Sym*)(m+dyn_tab[i].d_un.d_ptr); + } + if (dyn_tab[i].d_tag==DT_STRTAB) { + ret->dyn_str_tab = (char*)(m+dyn_tab[i].d_un.d_ptr); + } + if (dyn_tab[i].d_tag==DT_FINI) { + ret->fini = (void(*)(void))(m+dyn_tab[i].d_un.d_val); + } + if (dyn_tab[i].d_tag==DT_INIT) { + init = (void(*)(void))(m+dyn_tab[i].d_un.d_val); + printf("init @ %08x\n",init); + } + if (dyn_tab[i].d_tag==DT_PLTGOT) { + got=(unsigned long*)(m+dyn_tab[i].d_un.d_val); + } + if (dyn_tab[i].d_tag==DT_PLTREL) { + pltreltype=dyn_tab[i].d_un.d_val; + } + if (dyn_tab[i].d_tag==DT_PLTRELSZ) { + pltrelsize=dyn_tab[i].d_un.d_val; + } + if (dyn_tab[i].d_tag==DT_JMPREL) { + jmprel=(m+dyn_tab[i].d_un.d_val); + dl_test.plt_rel=jmprel; + } + } + /* GOT */ + got[0]+=(unsigned long)m; + got[1]=(unsigned long)&dl_test; +// got[2]=(unsigned long)do_rel; + got[2]=(unsigned long)(_dl_jump); + /* */ + + if (pltreltype == DT_REL) { + Elf32_Rel *tmp = jmprel; + for (;(char*)tmp<(((char*)jmprel)+pltrelsize);(char*)tmp=((char*)tmp)+sizeof(Elf32_Rel)) { + *((unsigned long*)(m+tmp->r_offset))+=(unsigned long)m; +// *((unsigned long*)(m+tmp->r_offset))+=(unsigned long)do_rel; + printf("rel @ %08x with type %d -> %d\n",tmp->r_offset,ELF32_R_TYPE(tmp->r_info),ELF32_R_SYM(tmp->r_info)); + } + } + + printf("_dl_open post resolv, pre init\n"); + init(); + } + printf("_dl_open post resolv, init\n"); + + close(fd); + return ret; +} diff --git a/mdk-stage1/dietlibc/libdl/_dl_search.c b/mdk-stage1/dietlibc/libdl/_dl_search.c new file mode 100644 index 000000000..5e3217d46 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/_dl_search.c @@ -0,0 +1,84 @@ +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> + +#include <fcntl.h> +#include <stdio.h> + +#define WANT_LD_SO_CONF_SEARCH + +static const char *_dl_search_rpath=0; +void _dl_set_rpath(const char *path) { _dl_search_rpath=path; } + +/* search a colon (semicolon) seperated path for the libraray "filename" */ +static int _dl_search_path(char *buf, int len, const char*path, const int pathlen, const char *filename) +{ + int fd,l=len,i=1; + const char *c,*pe=path+pathlen; + + if (path) { + for (c=path; c<pe; c+=i) { + if ((*c==':')||(*c==';')) ++c; + i=strcspn(c,":;"); + if (i) { + strncpy(buf, c, i); buf[i]=0; + l-=i; + strncat(buf, "/", l); + } + else + buf[0]=0; + strncat(buf, filename, --l); +// printf("_dl_search: %s\n",buf); + if ((fd=open(buf,O_RDONLY))!=-1) return fd; + } + } + return -1; +} + +/* parse the SMALL file "conf" for lib directories (aem... hang me if you can :) ) */ +static int _dl_search_conf(char *buf, int len, const char *conf, const char *filename) +{ + char ld_so_conf[1024]; + int i,l,fd=open(conf,O_RDONLY); + if (fd!=-1) { + l=read(fd,ld_so_conf,sizeof(ld_so_conf)-1); + ld_so_conf[sizeof(ld_so_conf)-1]=0; + close(fd); + if (ld_so_conf[l-1]=='\n') ld_so_conf[--l]=0; + for (i=0;i<l;i++) if (ld_so_conf[i]=='\n') ld_so_conf[i]=':'; + if ((fd=_dl_search_path(buf,len,ld_so_conf,l,filename))!=-1) return fd; + } + return -1; +} + +int _dl_search(char *buf, int len, const char *filename) +{ + int fd; + + /* 1. search the LD_RUN_PATH (from the executable */ + if (_dl_search_rpath) { + if ((fd=_dl_search_path(buf,len,_dl_search_rpath,strlen(_dl_search_rpath),filename))!=-1) return fd; + } + + /* 2. IF we have a "secure" enviroment THEN search LD_LIBRARY_PATH */ + if (getuid()==geteuid()) { + char *p=getenv("LD_LIBRARY_PATH"); + if (p) + if ((fd=_dl_search_path(buf,len,p,strlen(p),filename))!=-1) return fd; + } + + /* 3. search all pathes in the the /etc/diet.ld.conf, a dietlibc extension :) */ + if ((fd=_dl_search_conf(buf,len,"/etc/diet.ld.conf",filename))!=-1) return fd; + +#ifdef WANT_LD_SO_CONF_SEARCH + /* 4. search all pathes in the the /etc/ld.so.conf / can't handle this ...=lib?? crap */ + if ((fd=_dl_search_conf(buf,len,"/etc/ld.so.conf",filename))!=-1) return fd; +#endif + + /* default path search */ + { + const char* def_path="/usr/lib:/lib"; + return _dl_search_path(buf,len,def_path,strlen(def_path),filename); + } +} diff --git a/mdk-stage1/dietlibc/libdl/dlclose.c b/mdk-stage1/dietlibc/libdl/dlclose.c new file mode 100644 index 000000000..384550c47 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/dlclose.c @@ -0,0 +1,14 @@ +#include "_dl_int.h" + +int dlclose (void *handle) +{ + if (handle) { + struct _dl_handle *h = handle; + if (h->lnk_count) { + --h->lnk_count; + return -1; + } + if (munmap(h->mem_base,h->mem_size)!=0) return -1; + } + return 0; +} diff --git a/mdk-stage1/dietlibc/libdl/dlerror.c b/mdk-stage1/dietlibc/libdl/dlerror.c new file mode 100644 index 000000000..1e31bae54 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/dlerror.c @@ -0,0 +1,4 @@ +const char *dlerror(void) +{ + return "HAE ?!?"; +} diff --git a/mdk-stage1/dietlibc/libdl/dlopen.c b/mdk-stage1/dietlibc/libdl/dlopen.c new file mode 100644 index 000000000..1693d889f --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/dlopen.c @@ -0,0 +1,21 @@ +#include <fcntl.h> +#include <dlfcn.h> +#include <limits.h> + +int _dl_search(char*buf, int bufsize, const char*filename); +void *_dl_open(const char*pathname, int fd, int flag); + +void *dlopen (const char *filename, int flag) +{ + int fd; + char buf[PATH_MAX]; + const char *p; + if (*filename=='/') + fd=open(p=filename,O_RDONLY); + else { + p=buf; + fd=_dl_search(buf,sizeof(buf),filename); + } + + return _dl_open(p,fd,flag); +} diff --git a/mdk-stage1/dietlibc/libdl/dlsym.c b/mdk-stage1/dietlibc/libdl/dlsym.c new file mode 100644 index 000000000..2af940837 --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/dlsym.c @@ -0,0 +1,7 @@ +#include "_dl_int.h" + +void *dlsym(void *handle, char *symbol) +{ + printf("dlsym(%08x,%s) -> %08x\n",handle,symbol,elf_hash(symbol)%17); + return 0; +} diff --git a/mdk-stage1/dietlibc/libdl/elf_hash.c b/mdk-stage1/dietlibc/libdl/elf_hash.c new file mode 100644 index 000000000..463dba0dd --- /dev/null +++ b/mdk-stage1/dietlibc/libdl/elf_hash.c @@ -0,0 +1,12 @@ +unsigned long elf_hash(const unsigned char *name) +{ + unsigned long h=0, g; + + while (*name) + { + h = (h<<4) + *(name++); + if (g = h&0xf0000000) h ^= g>>24; + h &= ~g; + } + return h; +} diff --git a/mdk-stage1/dietlibc/libpthread/CHANGES b/mdk-stage1/dietlibc/libpthread/CHANGES new file mode 100644 index 000000000..d39d990ba --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/CHANGES @@ -0,0 +1,45 @@ +This is the pthread implementation of dietlibc. +Written from scratch by Olaf Dreesen. + +Thu Apr 12 16:47:12 MEST 2001 + + added conditional variables... + except pthread_cond_timedwait all should work man-page like + pthread_cond_timedwait dosen't handle cancel request according to man-page + + added thread specific key handling (all according to man-page) + +Fri Mar 30 18:47:37 MEST 2001 + + uff found some logic errors and fixed them. + pthread_create had a problem with user provided stacks. + + +Fri Mar 23 14:09:54 MET 2001 + + arg.. the kernel-header are so inconsistent... + on x86 it works on arm and sparc not due to MISSING defines, miss-places + includes and __KERNEL__ checks.... + the best in this category is that the kernel-header are changed that the + buggy (g)libc haven't to change... (f..k glibc, the headers HAVE to be + CONSISTENT) + a public defined symbol on arch X have to be in Y to unless marked... + that is mainly speaking SCHED.H ! arg.... + + +Wed Mar 14 04:28:45 MET 2001 + + I have implemented the "Manager Thread" so that nested thread creation + works. really ugly stuff... don't look at it unless you're sitting on solid + ground. + + +Mon Mar 12 16:16:00 CET 2001 + + first of all: + I strongly suggest NOT to use it yet, it's very, very, ... very + experimental. I guess you got the point. there is still much debug code, + incomplete functions and unusable states.... + + I'm still working on the final alpha... + diff --git a/mdk-stage1/dietlibc/libpthread/Makefile b/mdk-stage1/dietlibc/libpthread/Makefile new file mode 100644 index 000000000..06420f43a --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/Makefile @@ -0,0 +1,139 @@ +all: libpthread.a + +ARCH=$(shell uname -m | sed 's/i[4-9]86/i386/') + +CFLAGS=-pipe +CROSS= + +CC=gcc + +VPATH=../$(ARCH)/ + +PTHREAD_OBJS = \ + __testandset.o \ + \ + thread_internal.o \ + thread_key.o \ + \ + pthread_once.o pthread_spinlock.o \ + \ + pthread_create.o pthread_detach.o \ + pthread_join.o pthread_self.o \ + pthread_exit.o \ + \ + pthread_cleanup_push.o \ + pthread_cleanup_pop.o \ + \ + pthread_attr_getdetachstate.o \ + pthread_attr_getinheritsched.o \ + pthread_attr_getschedparam.o \ + pthread_attr_getschedpolicy.o \ + pthread_attr_getscope.o \ + pthread_attr_getstackaddr.o \ + pthread_attr_getstacksize.o \ + pthread_attr_init.o \ + pthread_attr_setdetachstate.o \ + pthread_attr_setinheritsched.o \ + pthread_attr_setschedparam.o \ + pthread_attr_setschedpolicy.o \ + pthread_attr_setscope.o \ + pthread_attr_setstackaddr.o \ + pthread_attr_setstacksize.o \ + \ + pthread_cancel.o pthread_setcancelstate.o \ + pthread_setcanceltype.o pthread_testcancel.o \ + \ + pthread_mutex_init.o \ + pthread_mutex_destroy.o \ + pthread_mutex_lock.o \ + pthread_mutex_trylock.o \ + pthread_mutex_unlock.o \ + \ + pthread_mutexattr_getkind_np.o \ + pthread_mutexattr_init.o \ + pthread_mutexattr_setkind_np.o \ + \ + pthread_condattr.o \ + pthread_cond_broadcast.o \ + pthread_cond_destroy.o \ + pthread_cond_init.o \ + pthread_cond_signal.o \ + pthread_cond_timedwait.o \ + pthread_cond_wait.o \ + \ + pthread_key_create.o \ + pthread_key_delete.o \ + pthread_getspecific.o \ + pthread_setspecific.o \ + \ + pthread_atfork.o \ + pthread_sys_alloc.o \ + pthread_sys_close.o \ + pthread_sys_create.o \ + pthread_sys_fcntl.o \ + pthread_sys_fsync.o \ + pthread_sys_nanosleep.o \ + pthread_sys_logging.o \ + pthread_sys_open.o \ + pthread_sys_pause.o \ + pthread_sys_read.o \ + pthread_sys_sigsuspend.o \ + pthread_sys_tcdrain.o \ + pthread_sys_waitpid.o \ + pthread_sys_write.o + +%.o : %.c + $(CC) $(CFLAGS) -c -o $@ $? + +include ../$(ARCH)/Makefile.add + +ifeq ($(CFLAGS),-pipe) +CFLAGS+=-O -fomit-frame-pointer +endif + +#CFLAGS = -g +CFLAGS += -Wall + +CFLAGS += -I.. -I../include -Wall + +PWD=$(shell pwd) + +.SUFFIXES: +.SUFFIXES: .S .c + +% :: %,v + +%.o: %.S + $(CROSS)$(CC) -I. -Iinclude $(CFLAGS) -c $< + +%.o: %.c + $(CROSS)$(CC) -I. -Iinclude $(CFLAGS) -c $< +# $(CROSS)strip -x -R .comment -R .note $@ + +libpthread.a: $(PTHREAD_OBJS) + ar cr $@ $^ + +libpthread.so: libpthread.a + $(CROSS)ld -whole-archive -shared -o $@ $^ + + +clean: + $(RM) *.o *.a *.so *.out *~ + +exports: libpthread.a + nm -g libpthread.a | grep -w T | awk '{ print $$3 }' | sort -u > exports + +.PHONY: test.out + +test.out: test.o libpthread.a $(LIBS) + $(CROSS)$(CC) -g $(CFLAGS) -nostdlib ../bin-$(ARCH)/start.o -o $@ $^ ../bin-$(ARCH)/dietlibc.a -lgcc + + +.PHONY: sparc ppc mips arm alpha i386 + +sparc ppc alpha i386: + $(MAKE) ARCH=$@ CROSS=$@-linux- all t libdietc.so + +mips arm: + $(MAKE) ARCH=$@ CROSS=$@-linux-gnu- all t libdietc.so + diff --git a/mdk-stage1/dietlibc/libpthread/README b/mdk-stage1/dietlibc/libpthread/README new file mode 100644 index 000000000..3139c731d --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/README @@ -0,0 +1,42 @@ +LIBPTHREAD + + This is the pthread implementation of dietlibc. + Written from scratch by Olaf Dreesen. + +1. STATUS: incomplete but should work (or not... I had a lot of heisen-bugs...) + On non i386 archs the kernel header have major differences... + NO workaround yet for this problems... + +It's like linuxthreads a clone base thread implementation. + +I have implemented a "Manager Thread" with all the pain it involves... +Nested thread creation is now working fine... + + +2. HOW-TO make this lib: + + 1. generate the dietlibc in the parent directory. + and make sure you have WANT_THREAD_SAVE active in the file: + dietfeatures.h + + 2. change back here and type make + + and then you should have a libpthread.a + + +3. NOTES + +NON STANDARD SIGNAL HANDLING for the threads: + + SIGHUP the targeted thread is canceled + depends on the cancel type of the thread. + + ASYNCHRONOUS: the signal handler will KILL the thread immediately. + + DEFERRED: the signal handler mark its thread as canceled. + (only for the sig-handler to do some sane stuff...) + + SIGTERM the thread is KILLED + if the thread signaled is the main thread, then ALL child-threads + will get a SIGHUP and after some micros a SIGTERM.... + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_atfork.c b/mdk-stage1/dietlibc/libpthread/pthread_atfork.c new file mode 100644 index 000000000..2dc612dcc --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_atfork.c @@ -0,0 +1,77 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +#define PTHREAD_NUM_ATFORK 4 + +static struct _pthread_fastlock __atfork_struct_lock; +static struct { + int used; + void (*prepare)(void); + void (*parent)(void); + void (*child)(void); +} pthread_atfork_buf[PTHREAD_NUM_ATFORK]; + +int pthread_atfork(void (*prepare)(void), + void (*parent)(void), + void (*child)(void)) +{ + int i,ret=-1; + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__atfork_struct_lock); + + for (i=0;i<PTHREAD_NUM_ATFORK; ++i) { + if (!(pthread_atfork_buf[i].used)) { + pthread_atfork_buf[i].prepare=prepare; + pthread_atfork_buf[i].parent=parent; + pthread_atfork_buf[i].child=child; + ret=0; + break; + } + } + + __pthread_unlock(&__atfork_struct_lock); + __NO_ASYNC_CANCEL_END; + + if (ret) (*(__errno_location()))=ENOMEM; + return ret; +} + +pid_t fork(void) +{ + pid_t pid; + int i=PTHREAD_NUM_ATFORK; + + __NO_ASYNC_CANCEL_BEGIN; + + __TEST_CANCEL(); + __pthread_lock(&__atfork_struct_lock); + + while (i) { + if (pthread_atfork_buf[--i].used) + if (pthread_atfork_buf[i].prepare) + pthread_atfork_buf[i].prepare(); + } + + pid=__libc_fork(); + + if (pid>0) { /* parent */ + for (i=0;i<PTHREAD_NUM_ATFORK;++i) + if (pthread_atfork_buf[i].used) + if (pthread_atfork_buf[i].parent) + pthread_atfork_buf[i].parent(); + } else if (pid==0) { /* child */ + for (i=0;i<PTHREAD_NUM_ATFORK;++i) + if (pthread_atfork_buf[i].used) + if (pthread_atfork_buf[i].child) + pthread_atfork_buf[i].child(); + } + + __pthread_unlock(&__atfork_struct_lock); + __NO_ASYNC_CANCEL_END; + + return pid; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getdetachstate.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getdetachstate.c new file mode 100644 index 000000000..ccdfc0e47 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getdetachstate.c @@ -0,0 +1,14 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + __THREAD_INIT(); + + *detachstate=attr->__detachstate; + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getinheritsched.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getinheritsched.c new file mode 100644 index 000000000..314fd8ade --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getinheritsched.c @@ -0,0 +1,13 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + __THREAD_INIT(); + + *inherit = attr->__inheritsched; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedparam.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedparam.c new file mode 100644 index 000000000..f0a9a07d1 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedparam.c @@ -0,0 +1,13 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) +{ + __THREAD_INIT(); + + param->sched_priority=attr->__schedparam.sched_priority; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedpolicy.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedpolicy.c new file mode 100644 index 000000000..53f1bed8c --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedpolicy.c @@ -0,0 +1,13 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + __THREAD_INIT(); + + *policy = attr->__schedpolicy; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getscope.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getscope.c new file mode 100644 index 000000000..99a33110d --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getscope.c @@ -0,0 +1,13 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + __THREAD_INIT(); + + *scope=PTHREAD_SCOPE_SYSTEM; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getstackaddr.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstackaddr.c new file mode 100644 index 000000000..d71421901 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstackaddr.c @@ -0,0 +1,13 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack) +{ + __THREAD_INIT(); + + *stack=attr->__stackaddr; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getstacksize.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstacksize.c new file mode 100644 index 000000000..4785979a0 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstacksize.c @@ -0,0 +1,14 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize) +{ + __THREAD_INIT(); + + *stacksize=attr->__stacksize; + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_init.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_init.c new file mode 100644 index 000000000..726e88fe5 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_init.c @@ -0,0 +1,17 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_init(pthread_attr_t *attr) +{ + __THREAD_INIT(); + + memset(attr,0,sizeof(pthread_attr_t)); + attr->__stacksize=PTHREAD_STACK_SIZE; + return 0; +} + +int pthread_attr_destroy(pthread_attr_t *attr) __attribute__((alias("pthread_attr_init"))); + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setdetachstate.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setdetachstate.c new file mode 100644 index 000000000..690ad5f8e --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setdetachstate.c @@ -0,0 +1,18 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + __THREAD_INIT(); + + if ((detachstate == PTHREAD_CREATE_JOINABLE) || + (detachstate == PTHREAD_CREATE_DETACHED)) { + attr->__detachstate=detachstate; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setinheritsched.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setinheritsched.c new file mode 100644 index 000000000..f38e6e35e --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setinheritsched.c @@ -0,0 +1,18 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + __THREAD_INIT(); + + if ((inherit==PTHREAD_INHERIT_SCHED) || + (inherit==PTHREAD_EXPLICIT_SCHED)) { + attr->__inheritsched=inherit; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedparam.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedparam.c new file mode 100644 index 000000000..833c0111b --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedparam.c @@ -0,0 +1,23 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) +{ + __THREAD_INIT(); + + if ((attr->__schedpolicy == SCHED_OTHER) && (param->sched_priority == 0)) { + attr->__schedparam.sched_priority=0; + return 0; + } + if (((attr->__schedpolicy == SCHED_RR) || (attr->__schedpolicy == SCHED_RR)) + && ((param->sched_priority > 0) && (param->sched_priority < 100))) { + attr->__schedparam.sched_priority=param->sched_priority; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedpolicy.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedpolicy.c new file mode 100644 index 000000000..e845bca32 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedpolicy.c @@ -0,0 +1,25 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + __THREAD_INIT(); + + if (policy==SCHED_OTHER) { + attr->__schedpolicy=policy; + return 0; + } + if ((policy==SCHED_FIFO) || (policy==SCHED_RR)) { + if (geteuid()==0) { + attr->__schedpolicy=policy; + return 0; + } + (*(__errno_location()))=ENOTSUP; + } + else + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setscope.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setscope.c new file mode 100644 index 000000000..39088c9b2 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setscope.c @@ -0,0 +1,18 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + __THREAD_INIT(); + + if (scope==PTHREAD_SCOPE_SYSTEM) return 0; + + if (scope==PTHREAD_SCOPE_PROCESS) + (*(__errno_location()))=ENOTSUP; + else + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setstackaddr.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstackaddr.c new file mode 100644 index 000000000..4b320cd9d --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstackaddr.c @@ -0,0 +1,13 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack) +{ + __THREAD_INIT(); + + attr->__stackaddr=stack; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setstacksize.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstacksize.c new file mode 100644 index 000000000..cfbab7747 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstacksize.c @@ -0,0 +1,17 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + __THREAD_INIT(); + + if (stacksize>=PTHREAD_STACK_SIZE) { + attr->__stacksize=stacksize; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cancel.c b/mdk-stage1/dietlibc/libpthread/pthread_cancel.c new file mode 100644 index 000000000..4c87a3ed1 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cancel.c @@ -0,0 +1,35 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_cancel(pthread_t th) +{ + pthread_t j; + _pthread_descr thread; + + __THREAD_INIT(); + + j=__find_thread_id(th); + + if (j==-1) { + (*(__errno_location()))=ESRCH; + return -1; + } + thread = __get_thread_struct(j); + + if (thread==0) { + (*(__errno_location()))=ESRCH; + return -1; + } + + if (thread->cancelstate!=PTHREAD_CANCEL_DISABLE) { + thread->canceled=1; + if (thread->canceltype!=PTHREAD_CANCEL_DEFERRED) { + kill(thread->pid,SIGHUP); + } + } + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cleanup_pop.c b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_pop.c new file mode 100644 index 000000000..641bb6083 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_pop.c @@ -0,0 +1,27 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +void pthread_cleanup_pop(int execute) +{ + _pthread_descr this; + struct thread_cleanup_t tmp; + int i=PTHREAD_MAX_CLEANUP; + + __THREAD_INIT(); + + this = __thread_self(); + + while(i>0) { + if (this->cleanup_stack[--i].func) { + tmp.func=this->cleanup_stack[i].func; + tmp.arg=this->cleanup_stack[i].arg; + this->cleanup_stack[i].func=0; + break; + } + } + + if (execute) tmp.func(tmp.arg); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cleanup_push.c b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_push.c new file mode 100644 index 000000000..cd2aabf71 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_push.c @@ -0,0 +1,23 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +void pthread_cleanup_push(void (*func)(void*), void *arg) +{ + _pthread_descr this; + int i; + + __THREAD_INIT(); + + this = __thread_self(); + + for (i=0; i<PTHREAD_MAX_CLEANUP; ++i) { + if (this->cleanup_stack[i].func==0) { + this->cleanup_stack[i].func=func; + this->cleanup_stack[i].arg=arg; + break; + } + } +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_broadcast.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_broadcast.c new file mode 100644 index 000000000..d3c2274f3 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_broadcast.c @@ -0,0 +1,23 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + _pthread_descr tmp; + + __THREAD_INIT(); + + __pthread_lock(&(cond->lock)); + while ((tmp=cond->wait_chain)) { + cond->wait_chain=tmp->waitnext; + tmp->waitnext=0; + tmp->waiting=0; + } + __pthread_unlock(&(cond->lock)); + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_destroy.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_destroy.c new file mode 100644 index 000000000..9a6cc4f0b --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_destroy.c @@ -0,0 +1,19 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_cond_destroy(pthread_cond_t *cond) +{ + __THREAD_INIT(); + + if (cond->wait_chain) { + (*__errno_location())=EBUSY; + return 1; + } + + memset(cond,0,sizeof(pthread_cond_t)); + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_init.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_init.c new file mode 100644 index 000000000..20b38bef2 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_init.c @@ -0,0 +1,14 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) +{ + __THREAD_INIT(); + + memset(cond,0,sizeof(pthread_cond_t)); + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_signal.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_signal.c new file mode 100644 index 000000000..60bf2119c --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_signal.c @@ -0,0 +1,24 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_cond_signal(pthread_cond_t *cond) +{ + _pthread_descr tmp=0; + + __THREAD_INIT(); + + __pthread_lock(&(cond->lock)); + if ((tmp=cond->wait_chain)) cond->wait_chain=tmp->waitnext; + __pthread_unlock(&(cond->lock)); + + if (tmp) { + tmp->waitnext=0; + tmp->waiting=0; + } + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_timedwait.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_timedwait.c new file mode 100644 index 000000000..6613f2ca9 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_timedwait.c @@ -0,0 +1,43 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + _pthread_descr tmp; + _pthread_descr this; + int ret; + + __THREAD_INIT(); + + this=__thread_self(); + + /* put in wait-chain */ + __pthread_lock(&(cond->lock)); + this->waiting=1; + if (cond->wait_chain) { + for(tmp=cond->wait_chain;tmp->waitnext;tmp=tmp->waitnext); + tmp->waitnext=this; + } else cond->wait_chain=this; + __pthread_unlock(&(cond->lock)); + + /* Aeh yeah / wait till signal */ + pthread_mutex_unlock(mutex); + ret=nanosleep(abstime,0); + pthread_mutex_lock(mutex); + + __TEST_CANCEL(); + + if (ret) { + if ((*__errno_location())!=EINTR) return -1; + return 0; + } + + (*__errno_location())=ETIMEDOUT; + return -1; +} + + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c new file mode 100644 index 000000000..0c6c0ae13 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c @@ -0,0 +1,37 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + _pthread_descr tmp; + _pthread_descr this; + + __THREAD_INIT(); + + this=__thread_self(); + + /* put in wait-chain */ + __pthread_lock(&(cond->lock)); + this->waiting=1; + if (cond->wait_chain) { + for(tmp=cond->wait_chain;tmp->waitnext;tmp=tmp->waitnext); + tmp->waitnext=this; + } else cond->wait_chain=this; + __pthread_unlock(&(cond->lock)); + + /* Aeh yeah / wait till signal */ + pthread_mutex_unlock(mutex); + while (this->waiting) { + __thread_wait_some_time(); + if (this->canceled) this->waiting=0; /* we got a cancel signal */ + } + pthread_mutex_lock(mutex); + + __TEST_CANCEL(); + return 0; +} + + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_condattr.c b/mdk-stage1/dietlibc/libpthread/pthread_condattr.c new file mode 100644 index 000000000..c537890ba --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_condattr.c @@ -0,0 +1,15 @@ +#include <pthread.h> + +int pthread_condattr_init(pthread_condattr_t *attr) +{ + return 0; +} + +int pthread_condattr_destroy(pthread_condattr_t *attr) +__attribute__((alias("pthread_condattr_init"))); + +int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared) +__attribute__((alias("pthread_condattr_init"))); + +int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared) +__attribute__((alias("pthread_condattr_init"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_create.c b/mdk-stage1/dietlibc/libpthread/pthread_create.c new file mode 100644 index 000000000..b4a499081 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_create.c @@ -0,0 +1,76 @@ +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg) +{ + int ret=0; + _pthread_descr td; + pthread_attr_t default_attr; + + __THREAD_INIT(); + + if (start_routine==0) { + (*(__errno_location()))=EINVAL; + return -1; + } + + td = __thread_get_free(); + + if (td) { + if (!(attr)) { + pthread_attr_init(&default_attr); + attr=&default_attr; + } + + if ((td->policy!=SCHED_OTHER)&&(td->priority==0)) { + (*(__errno_location()))=EINVAL; + return -1; + } + + if (attr->__inheritsched==PTHREAD_INHERIT_SCHED) { + _pthread_descr this = __thread_self(); + td->policy = this->policy; + td->priority = this->priority; + } else { + td->policy = attr->__schedpolicy; + td->priority = attr->__schedparam.sched_priority; + } + + td->func = start_routine; + td->arg = arg; + + td->detached = attr->__detachstate; + + td->stack_size = attr->__stacksize; + + if (!(td->stack_addr)) { + char *stack=(char*)malloc(td->stack_size); + if (!(stack)) { + (*(__errno_location()))=EINVAL; + return -1; + } + td->stack_begin = stack; + td->stack_addr = stack+td->stack_size; + } else { + td->stack_begin = 0; + td->stack_addr = attr->__stackaddr; + } + + ret = signal_manager_thread(td); + + if (ret>1) + *thread=ret; + else + __thread_cleanup(td); + } + else + (*(__errno_location()))=EAGAIN; + + if (ret<2) return -1; + return ret; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_detach.c b/mdk-stage1/dietlibc/libpthread/pthread_detach.c new file mode 100644 index 000000000..c07280389 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_detach.c @@ -0,0 +1,36 @@ +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_detach(pthread_t th) +{ + pthread_t j; + _pthread_descr thread; + + __THREAD_INIT(); + + j=__find_thread_id(th); + + if (j==-1) { + (*(__errno_location()))=ESRCH; + return -1; + } + thread = __get_thread_struct(j); + + if (thread==0) { + (*(__errno_location()))=ESRCH; + return -1; + } + + if (thread->detached) { + (*(__errno_location()))=EINVAL; + return -1; + } + + if (!thread->joined) { + thread->detached=1; + } + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_exit.c b/mdk-stage1/dietlibc/libpthread/pthread_exit.c new file mode 100644 index 000000000..41eac0a33 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_exit.c @@ -0,0 +1,17 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +void pthread_exit(void *retval) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + this->retval = retval; + + longjmp(this->jmp_exit,1); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_getspecific.c b/mdk-stage1/dietlibc/libpthread/pthread_getspecific.c new file mode 100644 index 000000000..c2f84c814 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_getspecific.c @@ -0,0 +1,20 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +const void *pthread_getspecific(pthread_key_t key) +{ + int id; + __THREAD_INIT(); + + id=__find_thread_id(getpid()); + + if ((key<PTHREAD_KEYS_MAX) && (__thread_keys[key].used)) { + return __thread_keys[key].tkd[id]; + } + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_join.c b/mdk-stage1/dietlibc/libpthread/pthread_join.c new file mode 100644 index 000000000..5b295bad1 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_join.c @@ -0,0 +1,50 @@ +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +#include "thread_internal.h" +#include <pthread.h> + +int pthread_join(pthread_t th, void **thread_return) +{ + pthread_t j; + _pthread_descr this, thread; + + __THREAD_INIT(); + + this = __thread_self(); + j=__find_thread_id(th); + + if (j==-1) { + (*(__errno_location()))=ESRCH; + return -1; + } + + thread = __get_thread_struct(j); + + /* error handling */ + if (thread==0) { + (*(__errno_location()))=ESRCH; + return -1; + } + + if (this==thread) { + (*(__errno_location()))=EDEADLK; + return -1; + } + + if (thread->detached || thread->joined) { + (*(__errno_location()))=EINVAL; + return -1; + } + + thread->joined=this; + this->join=1; + + while(this->join) __thread_wait_some_time(); + + if (thread_return) *thread_return=this->retval; + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_key_create.c b/mdk-stage1/dietlibc/libpthread/pthread_key_create.c new file mode 100644 index 000000000..44fccea6a --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_key_create.c @@ -0,0 +1,35 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +extern struct _pthread_fastlock __thread_keys_lock; +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +int pthread_key_create(pthread_key_t *key, void (*destructor)(const void*)) +{ + int ret=-1,i; + + __THREAD_INIT(); + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__thread_keys_lock); + + for (i=0; i<PTHREAD_KEYS_MAX; i++) { + if (!__thread_keys[i].used) { + __thread_keys[i].used=1; + __thread_keys[i].destructor=destructor; + memset(__thread_keys[i].tkd,0,PTHREAD_THREADS_MAX*sizeof(struct _thread_key)); + *key=i; + ret=0; + break; + } + } + + __pthread_unlock(&__thread_keys_lock); + __NO_ASYNC_CANCEL_END; + + if (ret) (*__errno_location())=EAGAIN; + return ret; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_key_delete.c b/mdk-stage1/dietlibc/libpthread/pthread_key_delete.c new file mode 100644 index 000000000..b1bc366e2 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_key_delete.c @@ -0,0 +1,21 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +int pthread_key_delete(pthread_key_t key) +{ + __THREAD_INIT(); + + if (key>=PTHREAD_KEYS_MAX) { + (*__errno_location())=EINVAL; + return -1; + } + + __thread_keys[key].used=0; + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_destroy.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_destroy.c new file mode 100644 index 000000000..33a16abd4 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_destroy.c @@ -0,0 +1,16 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + __THREAD_INIT(); + + if ((mutex->owner)||(mutex->lock.__spinlock)) { + (*(__errno_location()))=EBUSY; + return -1; + } + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_init.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_init.c new file mode 100644 index 000000000..b1797fb20 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_init.c @@ -0,0 +1,18 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_mutex_init(pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutexattr) +{ + __THREAD_INIT(); + + memset(mutex,0,sizeof(pthread_mutex_t)); + if (mutexattr) { + mutex->kind=mutexattr->__mutexkind; + } + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_lock.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_lock.c new file mode 100644 index 000000000..0c3ade9e8 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_lock.c @@ -0,0 +1,33 @@ +#include <unistd.h> +#include <sched.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +/* will never return EINVAL ! */ + +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + + if (this!=mutex->owner) { + /* wait for mutex to free */ + __pthread_lock(&(mutex->lock)); + + mutex->owner=this; + } + else if (mutex->kind==PTHREAD_MUTEX_ERRORCHECK_NP) + { + (*(__errno_location()))=EDEADLK; + return -1; + } + + if (mutex->kind==PTHREAD_MUTEX_RECURSIVE_NP) ++(mutex->count); + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_trylock.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_trylock.c new file mode 100644 index 000000000..fcf63f75e --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_trylock.c @@ -0,0 +1,36 @@ +#include <unistd.h> +#include <sched.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +/* will never return EINVAL ! */ + +int pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + + if (this!=mutex->owner) { + /* wait for mutex to free */ + if (__pthread_trylock(&(mutex->lock))) { + (*(__errno_location()))=EBUSY; + return -1; + } + + mutex->owner=this; + } + else if (mutex->kind==PTHREAD_MUTEX_ERRORCHECK_NP) + { + (*(__errno_location()))=EDEADLK; + return -1; + } + + if (mutex->kind==PTHREAD_MUTEX_RECURSIVE_NP) ++(mutex->count); + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_unlock.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_unlock.c new file mode 100644 index 000000000..0b5a1d0f7 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_unlock.c @@ -0,0 +1,34 @@ +#include <unistd.h> +#include <sched.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +/* will never return EINVAL ! */ + +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + + if (this==mutex->owner) { + if (mutex->kind==PTHREAD_MUTEX_RECURSIVE_NP) { + if (--(mutex->count)) + return 0; + } + + mutex->owner=0; + __pthread_unlock(&(mutex->lock)); + } + else if (mutex->kind==PTHREAD_MUTEX_ERRORCHECK_NP) + { + (*(__errno_location()))=EPERM; + return -1; + } + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_getkind_np.c b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_getkind_np.c new file mode 100644 index 000000000..63cd9133c --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_getkind_np.c @@ -0,0 +1,13 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_mutexattr_getkind_np(const pthread_mutexattr_t *attr, int *kind) +{ + __THREAD_INIT(); + + *kind=attr->__mutexkind; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_init.c b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_init.c new file mode 100644 index 000000000..ff60e4c74 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_init.c @@ -0,0 +1,15 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + __THREAD_INIT(); + + attr->__mutexkind = 0; + return 0; +} + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) __attribute__((alias ("pthread_mutexattr_init"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_setkind_np.c b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_setkind_np.c new file mode 100644 index 000000000..ac600f8ed --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_setkind_np.c @@ -0,0 +1,18 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind) +{ + __THREAD_INIT(); + + if ((kind==PTHREAD_MUTEX_FAST_NP) || (kind==PTHREAD_MUTEX_RECURSIVE_NP) || + (kind==PTHREAD_MUTEX_ERRORCHECK_NP)) { + attr->__mutexkind=kind; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_once.c b/mdk-stage1/dietlibc/libpthread/pthread_once.c new file mode 100644 index 000000000..16d9cb392 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_once.c @@ -0,0 +1,9 @@ +#include <pthread.h> +#include "thread_internal.h" + +int __pthread_once (pthread_once_t* once_control, void (*init_routine)(void)) +{ + if (!(__testandset(once_control))) init_routine(); + return 0; +} +int pthread_once (pthread_once_t* once_control, void (*init_routine)(void)) __attribute__((alias("__pthread_once"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_self.c b/mdk-stage1/dietlibc/libpthread/pthread_self.c new file mode 100644 index 000000000..394686dd4 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_self.c @@ -0,0 +1,4 @@ +#include <unistd.h> +#include <pthread.h> + +pthread_t pthread_self() { return getpid(); } diff --git a/mdk-stage1/dietlibc/libpthread/pthread_setcancelstate.c b/mdk-stage1/dietlibc/libpthread/pthread_setcancelstate.c new file mode 100644 index 000000000..b906492fb --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_setcancelstate.c @@ -0,0 +1,25 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_setcancelstate(int state, int *oldstate) +{ + _pthread_descr thread; + + __THREAD_INIT(); + + if ((state==PTHREAD_CANCEL_ENABLE) || (state==PTHREAD_CANCEL_DISABLE)) + { + thread = __thread_self(); + + if (oldstate) *oldstate = thread->cancelstate; + thread->cancelstate = state; + + return 0; + } + + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_setcanceltype.c b/mdk-stage1/dietlibc/libpthread/pthread_setcanceltype.c new file mode 100644 index 000000000..03d1f53de --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_setcanceltype.c @@ -0,0 +1,25 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pthread_setcanceltype(int type, int *oldtype) +{ + _pthread_descr thread; + + __THREAD_INIT(); + + if ((type==PTHREAD_CANCEL_DEFERRED) || (type==PTHREAD_CANCEL_ASYNCHRONOUS)) + { + thread = __thread_self(); + + if (oldtype) *oldtype = thread->canceltype; + thread->canceltype = type; + + return 0; + } + + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_setspecific.c b/mdk-stage1/dietlibc/libpthread/pthread_setspecific.c new file mode 100644 index 000000000..78339c20b --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_setspecific.c @@ -0,0 +1,21 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +int pthread_setspecific(pthread_key_t key, const void *value) +{ + int id; + __THREAD_INIT(); + + id=__find_thread_id(getpid()); + if ((key<PTHREAD_KEYS_MAX) && (__thread_keys[key].used)) { + __thread_keys[key].tkd[id]=value; + return 0; + } + (*__errno_location())=EINVAL; + return -1; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_spinlock.c b/mdk-stage1/dietlibc/libpthread/pthread_spinlock.c new file mode 100644 index 000000000..449782adf --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_spinlock.c @@ -0,0 +1,38 @@ +#include <time.h> +#include <pthread.h> +#include "thread_internal.h" + +static void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + struct timespec tm; + + while (__testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + sched_yield(); + cnt++; + } else { + tm.tv_sec = 0; + tm.tv_nsec = SPIN_SLEEP_DURATION; + __libc_nanosleep(&tm, 0); + cnt = 0; + } + } +} + +void __pthread_lock(struct _pthread_fastlock * lock) +{ + __pthread_acquire(&lock->__spinlock); +} + +int __pthread_trylock(struct _pthread_fastlock * lock) +{ + return __testandset(&lock->__spinlock); +} + +int __pthread_unlock(struct _pthread_fastlock * lock) +{ + return (lock->__spinlock = 0); +} + + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c new file mode 100644 index 000000000..9f7d23d79 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c @@ -0,0 +1,26 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +static pthread_mutex_t mutex_alloc = PTHREAD_MUTEX_INITIALIZER; + +void free(void *ptr) +{ + __NO_ASYNC_CANCEL_BEGIN; + pthread_mutex_lock(&mutex_alloc); + __libc_free(ptr); + pthread_mutex_unlock(&mutex_alloc); + __NO_ASYNC_CANCEL_END; +} + +void *malloc(size_t size) +{ + register void *ret; + __NO_ASYNC_CANCEL_BEGIN; + pthread_mutex_lock(&mutex_alloc); + ret=__libc_malloc(size); + pthread_mutex_unlock(&mutex_alloc); + __NO_ASYNC_CANCEL_END; + return ret; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_close.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_close.c new file mode 100644 index 000000000..84d5d5f36 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_close.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int close(int fd) +{ + __TEST_CANCEL(); + return __libc_close(fd); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_create.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_create.c new file mode 100644 index 000000000..9d47844f5 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_create.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int creat(const char *pathname, mode_t mode) +{ + __TEST_CANCEL(); + return __libc_creat(pathname,mode); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c new file mode 100644 index 000000000..99210a488 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int fcntl(int fd, int cmd, void *arg) +{ + __TEST_CANCEL(); + return __libc_fcntl(fd,cmd,arg); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c new file mode 100644 index 000000000..a2c995069 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int fsync(int fd) +{ + __TEST_CANCEL(); + return __libc_fsync(fd); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_logging.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_logging.c new file mode 100644 index 000000000..6070ad219 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_logging.c @@ -0,0 +1,31 @@ +#include <unistd.h> +#include <stdarg.h> + +#include <pthread.h> +#include "thread_internal.h" + +static pthread_mutex_t mutex_syslog = PTHREAD_MUTEX_INITIALIZER; + +void closelog(void) +{ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,&mutex_syslog); + pthread_mutex_lock(&mutex_syslog); + __libc_closelog(); + pthread_cleanup_pop(1); +} + +void openlog(const char *ident, int option, int facility) +{ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,&mutex_syslog); + pthread_mutex_lock(&mutex_syslog); + __libc_openlog(ident, option, facility); + pthread_cleanup_pop(1); +} + +void vsyslog(int priority, const char *format, va_list arg_ptr) +{ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,&mutex_syslog); + pthread_mutex_lock(&mutex_syslog); + __libc_vsyslog(priority, format, arg_ptr); + pthread_cleanup_pop(1); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_nanosleep.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_nanosleep.c new file mode 100644 index 000000000..699de4654 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_nanosleep.c @@ -0,0 +1,11 @@ +#include <time.h> +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int nanosleep(const struct timespec *req, struct timespec *rem) +{ + __TEST_CANCEL(); + return __libc_nanosleep(req,rem); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_open.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_open.c new file mode 100644 index 000000000..513f6a323 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_open.c @@ -0,0 +1,12 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int __pthread_open(const char *pathname, int flags, mode_t mode) +{ + __TEST_CANCEL(); + return __libc_open(pathname,flags,mode); +} + +int open(const char *pathname, int flags, ...) __attribute__((alias("__pthread_open"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c new file mode 100644 index 000000000..ab15ead11 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int pause() +{ + __TEST_CANCEL(); + return __libc_pause(); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_read.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_read.c new file mode 100644 index 000000000..60f886003 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_read.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int read(int fd, void *buf, size_t count) +{ + __TEST_CANCEL(); + return __libc_read(fd,buf,count); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_sigsuspend.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_sigsuspend.c new file mode 100644 index 000000000..72cd783ae --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_sigsuspend.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int sigsuspend(const sigset_t *mask) +{ + __TEST_CANCEL(); + return __libc_sigsuspend(mask); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_tcdrain.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_tcdrain.c new file mode 100644 index 000000000..1ac33adfc --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_tcdrain.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int tcdrain(int fd) +{ + __TEST_CANCEL(); + return __libc_tcdrain(fd); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_waitpid.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_waitpid.c new file mode 100644 index 000000000..76d5ddca7 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_waitpid.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +pid_t waitpid(pid_t pid, int *status, int options) +{ + __TEST_CANCEL(); + return __libc_waitpid(pid,status,options); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_write.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_write.c new file mode 100644 index 000000000..37541ae42 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_write.c @@ -0,0 +1,10 @@ +#include <unistd.h> + +#include <pthread.h> +#include "thread_internal.h" + +int write(int fd, const void *buf, size_t count) +{ + __TEST_CANCEL(); + return __libc_write(fd,buf,count); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_testcancel.c b/mdk-stage1/dietlibc/libpthread/pthread_testcancel.c new file mode 100644 index 000000000..68f91e743 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_testcancel.c @@ -0,0 +1,16 @@ +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +void pthread_testcancel() +{ + _pthread_descr thread; + __THREAD_INIT(); + + thread=__thread_self(); + + if (thread->canceled) { + pthread_exit(PTHREAD_CANCELED); + } +} diff --git a/mdk-stage1/dietlibc/libpthread/test.c b/mdk-stage1/dietlibc/libpthread/test.c new file mode 100644 index 000000000..3272c1753 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/test.c @@ -0,0 +1,72 @@ +#include <stdio.h> +#include <pthread.h> + +#include <unistd.h> +#include <signal.h> + +#include <errno.h> + +int ra; + +void test(int sig) +{ + printf("SIGNAL %d in %d\n",sig,getpid()); + fflush(stdout); + signal(SIGHUP, test); +} + +void* thread(void* arg) +{ + int i; + for (i=0;i<10; i++) + { + printf("child %ld %8p\n", pthread_self(),arg); + sleep(1); + } + return arg; +} + +void* thread2(void *arg) +{ + pthread_t t; + int i; + + printf("child %ld %8p\n", pthread_self(),arg); + for (i=0; i<3; ++i) { + printf("child starting next in %d secs %ld %8p\n", 3-i, pthread_self(),arg); + sleep(1); + } + pthread_create(&t,0, thread, (void*)2); + printf("new child @ %ld\n",t); + return (void*)t; +} + +int main(int argc, char*argv[]) +{ + pthread_t t; + + signal(SIGHUP, test); + + pthread_create(&t,0, thread2, 0); + pthread_create(&t,0, thread, (void *)3); + pthread_create(&t,0, thread, (void *)1); + + puts("main"); + +#if 0 + { + int i; + for(i=0;i<4;i++) sleep(1); + } +#else + { + int *tt; + int i = pthread_join(t,(void*)&tt); + printf("join %d %p %d\n",i,tt,(*(__errno_location()))); + } +#endif + + puts("main exit"); + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/thread_internal.c b/mdk-stage1/dietlibc/libpthread/thread_internal.c new file mode 100644 index 000000000..a93806203 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/thread_internal.c @@ -0,0 +1,344 @@ +#include <signal.h> +#include <string.h> +#include <sys/wait.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +#include <sched.h> +#include <sys/resource.h> + +#include <stdio.h> +#include "thread_internal.h" + +static struct _pthread_fastlock __thread_struct_lock = {0}; +static struct _pthread_descr_struct threads[PTHREAD_THREADS_MAX]; +static int _max_used_thread_id=1; +pthread_once_t __thread_inited; + +static struct _pthread_fastlock __manager_thread_signal_lock = {0}; +static struct _pthread_fastlock __manager_thread_data_lock = {1}; +static struct _pthread_fastlock __manager_thread_data_go_lock = {1}; + +//#define DEBUG + +/* find thread */ +int __find_thread_id(int pid) +{ + register int i; + for (i=0; i<_max_used_thread_id; i++) + if (threads[i].pid==pid) + return i; + return -1; +} + +/* get thread */ +_pthread_descr __get_thread_struct(int id) +{ + return threads+id; +} + +/* thread errno location */ +int *__errno_location(void) +{ + int id=0; + if (__thread_inited) id=__find_thread_id(getpid()); + if (id<0) + return 0; + else + return &threads[id].errno; +} + +/* thread self */ +_pthread_descr __thread_self() +{ + register int i=__find_thread_id(getpid()); + if (i<0) + return 0; + else + return threads+i; +} + +/* allocate a thread slot */ +_pthread_descr __thread_get_free() +{ + _pthread_descr ret=0; + int i; + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__thread_struct_lock); + + for (i=0; i<PTHREAD_THREADS_MAX; i++) { + if (threads[i].pid==0) { + threads[i].pid=1; /* mark as taken */ + ret = threads+i; + if (i>=_max_used_thread_id) _max_used_thread_id=i+1; + break; + } + } + + __pthread_unlock(&__thread_struct_lock); + __NO_ASYNC_CANCEL_END; + return ret; +} + +/* sleep a little (reschedule for this time) */ +void __thread_wait_some_time() +{ + struct timespec reg; + reg.tv_sec=0; + reg.tv_nsec=SPIN_SLEEP_DURATION; + __libc_nanosleep(®,0); +} + +/* cleanup a thread struct */ +void __thread_cleanup(_pthread_descr th) +{ + /* lib provided stack should be freed */ + if (th->stack_begin) free(th->stack_begin); + + /* an other thread has joined this on */ + if (th->joined) { + th->joined->retval=th->retval; + th->joined->join=0; + th->joined=0; + } + th->pid=0; /* mark struct as free */ +} + +/* SIGHUP handler (thread cnacel) PTHREAD_CANCEL_ASYNCHRONOUS */ +static void __thread_cancel_handler(int sig) +{ + _pthread_descr this; + this = __thread_self(); + this->canceled=1; + if (this->canceltype==PTHREAD_CANCEL_ASYNCHRONOUS) + pthread_exit(PTHREAD_CANCELED); + signal( SIGHUP, __thread_cancel_handler ); +} + +/* kill ALL threads / other then prime task and manager thread */ +static void __kill_all_threads() +{ + int i; + + for (i=2; i<_max_used_thread_id; i++) { + if (threads[i].pid>1) { +#ifdef DEBUG + printf("CANCEL ! %d\n",threads[i].pid); +#endif + threads[i].canceled=1; + kill(threads[i].pid, SIGHUP); /* cancel thread */ + } + } + + __thread_wait_some_time(); + + for (i=2; i<_max_used_thread_id; i++) { + if (threads[i].pid>1) { +#ifdef DEBUG + printf("KILL ! %d\n",threads[i].pid); +#endif + kill(threads[i].pid, SIGTERM); /* KILL thread */ + } + } +} + +__attribute__((weak)) volatile void __thread_start__key(int id) { return; } +__attribute__((weak,alias("__thread_start__key"))) volatile void __thread_exit__key(int id); + +/* support for manager */ +static void *__mthread_starter(void *arg) +{ + _pthread_descr td = (_pthread_descr)arg; + int i = td->stack_size-4096; + + /* just to be sure */ + td->pid=getpid(); + + /* signal handling for a thread */ + signal(SIGTERM, _exit); + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, __thread_cancel_handler ); + + /* limit stack so that we NEVER have to worry */ + setrlimit(RLIMIT_STACK, (struct rlimit *)(&i)); + + /* set scheduler */ + if (td->policy!=SCHED_OTHER) { + struct sched_param sp; + sp.sched_priority=td->priority; + sched_setscheduler(td->pid,td->policy, &sp); + } + + /* thread_key glue */ + __thread_start__key(td-threads); + +#ifdef DEBUG + printf("in starter %d, parameter %8p\n", td->pid, td->func); +#endif + + if (!td->canceled) { + if (!(setjmp(td->jmp_exit))) { + td->retval=td->func(td->arg); +#ifdef DEBUG + } else { + printf("pthread_exit called in %d\n", td->pid); +#endif + } + } + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); + + /* thread_key glue */ + __thread_exit__key(td-threads); + +#ifdef DEBUG + printf("end starter %d, retval %8p\n", td->pid, td->retval); +#endif + + /* wake joined thread and put retval */ + if (td->joined) { + td->joined->retval=td->retval; + td->joined->join=0; + td->joined=0; + } + + /* execute all functions on the cleanup-stack */ + for (i=PTHREAD_MAX_CLEANUP;i;) { + if (td->cleanup_stack[--i].func) { + td->cleanup_stack[i].func(td->cleanup_stack[i].arg); + } + } + + return 0; +} + + +/* manager thread and signal handler */ +static char __manager_thread_stack[12*1024]; +static volatile _pthread_descr __manager_thread_data; +static void __manager_SIGCHLD(int sig) +{ + int pid, status, i; + + while(1) { + pid = __libc_waitpid (-1, &status, WNOHANG); + if (pid <= 0) break; + + for (i=0; i<_max_used_thread_id; i++) { + if (threads[i].pid==pid) { + __thread_cleanup(threads+i); + break; + } + } + } +} + +static void __manager_SIGTERM(int sig) +{ + __kill_all_threads(); + _exit(0); +} + +static void* __manager_thread(void *arg) +{ + struct sigaction sig_action_chld; + sig_action_chld.sa_handler = __manager_SIGCHLD; + sigemptyset(&sig_action_chld.sa_mask); + sig_action_chld.sa_flags = SA_RESTART; + + sigaction(SIGCHLD, &sig_action_chld, 0); + signal(SIGTERM, __manager_SIGTERM); + signal(SIGHUP, SIG_IGN); + + __pthread_unlock(&__manager_thread_data_go_lock); /* release init */ + while(1) { + do { + __thread_wait_some_time(); + if (getppid()<0) __manager_SIGTERM(0); + } while (__pthread_trylock(&__manager_thread_data_lock)); + + __manager_thread_data->pid = + __clone(__mthread_starter, + __manager_thread_data->stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, + __manager_thread_data); + __thread_wait_some_time(); +#ifdef DEBUG + printf("manager new thread %d\n",__manager_thread_data->pid); +#endif + __pthread_unlock(&__manager_thread_data_go_lock); /* release sender */ + } + return 0; +} + +/* pthread_create bottom half */ +int signal_manager_thread(_pthread_descr td) +{ + __NO_ASYNC_CANCEL_BEGIN; + + __pthread_lock(&__manager_thread_signal_lock); /* lock */ + + __manager_thread_data = td; + __thread_wait_some_time(); + __pthread_unlock(&__manager_thread_data_lock); /* signal manager to start */ + __thread_wait_some_time(); + __pthread_lock(&__manager_thread_data_go_lock); /* wait for manager */ + + __pthread_unlock(&__manager_thread_signal_lock); /* unlock */ + + __NO_ASYNC_CANCEL_END; + + return td->pid; +} + + +/* thread stop */ +static void __thread_main_exit() +{ + if (getpid()!=threads[0].pid) { +#ifdef DEBUG + printf("A THREAD ? %d\n",getpid()); +#endif + kill(threads[0].pid, SIGTERM); + while(1) __thread_wait_some_time(); + } +#ifdef DEBUG + else + printf("EXIT ! %d\n",getpid()); +#endif + + /* stop ALL threads */ + kill(threads[1].pid, SIGTERM); + __thread_wait_some_time(); + __kill_all_threads(); +} + +/* thread intern init */ +void __thread_init() +{ + if (atexit(__thread_main_exit)==-1) + exit(42); + +#ifdef DEBUG + printf("INIT ! %d\n",getpid()); + memset(threads,0,sizeof(threads)); +#endif + + threads[0].pid = getpid(); + + ++_max_used_thread_id; + threads[1].stack_size=sizeof(__manager_thread_stack); + threads[1].stack_addr=&__manager_thread_stack[sizeof(__manager_thread_stack)]; + threads[1].stack_begin=0; + threads[1].func=__manager_thread; + + threads[1].pid = __clone(__mthread_starter, threads[1].stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES, threads+1); + +#ifdef DEBUG + printf("manager thread @ : %d\n",threads[1].pid); +#endif + __pthread_lock(&__manager_thread_data_go_lock); /* wait for manager to be ready */ +} + diff --git a/mdk-stage1/dietlibc/libpthread/thread_internal.h b/mdk-stage1/dietlibc/libpthread/thread_internal.h new file mode 100644 index 000000000..5eb3bbd08 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/thread_internal.h @@ -0,0 +1,131 @@ +#ifndef __THREAD_INTERNAL_H__ +#define __THREAD_INTERNAL_H__ + +#include <pthread.h> +#include <stdarg.h> +#include <setjmp.h> +#include "dietfeatures.h" +#ifndef WANT_THREAD_SAFE +#error "the diet libc is not compiled with thread safeness enabled!" +#endif + +/* cleanup */ +#define PTHREAD_MAX_CLEANUP 8 +struct thread_cleanup_t { + void (*func)(void*); + void *arg; +}; + +/* the thread descriptor / internal */ +struct _pthread_descr_struct { + /* runtime handling */ + struct _pthread_descr_struct *joined; /* a joined thread or NULL */ + + /* conditional variables */ + struct _pthread_descr_struct *waitnext; /* an other waiting thread or NULL */ + int waiting; /* internal waiting "lock" */ + + /* thread/process data */ + int pid; /* Process id */ + + int policy; /* thread scheduling policy */ + int priority; /* thread priority */ + + /* errno handling */ + int errno; + int h_errno; + + /* stack handling */ + unsigned int stack_size; /* stack size for setrlimit */ + void *stack_addr; /* stack address for clone */ + void *stack_begin; /* begin of lib-stack / lowest address (free) */ + + /* thread exit handling */ + void *retval; /* thread return value */ + int join; /* thread waits for other to return */ + jmp_buf jmp_exit; /* pthread_exit jump */ + + /* thread flags */ + int detached; /* thread is detached */ + int canceled; /* thread canceled */ + + /* cancel handling */ + int cancelstate; /* cancel state */ + int canceltype; /* type of cancellation */ + + /* thread basics */ + void* (*func) (void* arg); /* thread function */ + void* arg; /* thread argument */ + + /* create thread / manager thread lock */ + struct _pthread_fastlock *manager_lock; + + /* cleanup stack */ + struct thread_cleanup_t cleanup_stack[PTHREAD_MAX_CLEANUP]; + +} __attribute__ ((aligned(32))); + +/* thread keys */ +struct _thread_key { + int used; + void (*destructor)(const void*); + const void *tkd[PTHREAD_THREADS_MAX]; +}; + +/* internal stuff */ +int __testandset(int *spinlock); + +void __pthread_lock(struct _pthread_fastlock * lock); +int __pthread_trylock(struct _pthread_fastlock * lock); +int __pthread_unlock(struct _pthread_fastlock * lock); + +int __clone(void* (*fn)(void*), void* stack, int flags, void *arg); + +int __find_thread_id(int pid); +_pthread_descr __get_thread_struct(int id); + +_pthread_descr __thread_get_free(); +_pthread_descr __thread_self(); + +void __thread_cleanup(_pthread_descr th); + +void __thread_wait_some_time(); + +#define __NO_ASYNC_CANCEL_BEGIN { int oldtype; pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); +#define __NO_ASYNC_CANCEL_END pthread_setcanceltype(oldtype,0); pthread_testcancel(); } +#define __NO_ASYNC_CANCEL_STOP pthread_setcanceltype(oldtype,0); } + +/* manager thread stuff */ +int signal_manager_thread(_pthread_descr td); + +/* init stuff */ +extern pthread_once_t __thread_inited; +void __thread_init(); +#define __THREAD_INIT() __pthread_once(&__thread_inited, __thread_init) +#define __TEST_CANCEL() pthread_testcancel() + +/* diet libc syscalls */ + +void __libc_free(void *ptr); +void *__libc_malloc(size_t size); + +void __libc_closelog(void); +void __libc_openlog(const char *ident, int option, int facility); +void __libc_vsyslog(int priority, const char *format, va_list arg_ptr); + +pid_t __libc_fork(void); + +int __libc_close(int fd); +int __libc_creat(const char *pathname, mode_t mode); +int __libc_fcntl(int fd, int cmd, void *arg); +int __libc_fsync(int fd); +int __libc_nanosleep(const struct timespec *req, struct timespec *rem); +int __libc_open(const char *pathname, int flags, mode_t mode); +int __libc_pause(void); +int __libc_read(int fd, void *buf, size_t count); +int __libc_sigsuspend(const sigset_t *mask); +int __libc_tcdrain(int fd); +pid_t __libc_waitpid(pid_t pid, int *status, int options); +int __libc_write(int fd, const void *buf, size_t count); + +#endif diff --git a/mdk-stage1/dietlibc/libpthread/thread_key.c b/mdk-stage1/dietlibc/libpthread/thread_key.c new file mode 100644 index 000000000..b0f719fc9 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/thread_key.c @@ -0,0 +1,41 @@ +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> +#include "thread_internal.h" + +struct _pthread_fastlock __thread_keys_lock; +struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; + +void __thread_start__key(int id) +{ + int i; + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__thread_keys_lock); + + for (i=0; i<PTHREAD_KEYS_MAX; i++) { + __thread_keys[i].tkd[id]=0; + } + + __pthread_unlock(&__thread_keys_lock); + __NO_ASYNC_CANCEL_END; +} + +void __thread_exit__key(int id) +{ + int i,try; + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__thread_keys_lock); + + for (i=0; i<PTHREAD_KEYS_MAX; i++) { + if ((__thread_keys[i].used) && (__thread_keys[i].destructor)) { + for (try=0;__thread_keys[i].tkd[id] && (try<PTHREAD_DESTRUCTOR_ITERATIONS);++try) + __thread_keys[i].destructor(__thread_keys[i].tkd[id]); + } + } + + __pthread_unlock(&__thread_keys_lock); + __NO_ASYNC_CANCEL_STOP; +} |