diff options
Diffstat (limited to 'ndb/src/common/portlib')
44 files changed, 4476 insertions, 0 deletions
diff --git a/ndb/src/common/portlib/Makefile b/ndb/src/common/portlib/Makefile new file mode 100644 index 00000000000..a928fc1e6d7 --- /dev/null +++ b/ndb/src/common/portlib/Makefile @@ -0,0 +1,43 @@ +include .defs.mk + +DIRS := + +ifeq ($(NDB_OS), SOFTOSE) +DIRS += ose +endif + +ifeq ($(NDB_OS), OSE) +DIRS += ose +endif + +ifeq ($(NDB_OS), SIMCELLO) +DIRS += ose +endif + +ifeq ($(NDB_OS), LINUX) +DIRS += unix +endif + +ifeq ($(NDB_OS), MACOSX) +DIRS += unix +endif + +ifeq ($(NDB_OS), SOLARIS) +DIRS += unix +endif + +ifeq ($(NDB_OS), SOLARIS6) +DIRS += unix +endif + +ifeq ($(NDB_OS), HPUX) +DIRS += unix +endif + +ifeq ($(NDB_OS), WIN32) +DIRS += win32 +endif + + +include $(NDB_TOP)/Epilogue.mk + diff --git a/ndb/src/common/portlib/memtest/Makefile b/ndb/src/common/portlib/memtest/Makefile new file mode 100644 index 00000000000..716cdbdea82 --- /dev/null +++ b/ndb/src/common/portlib/memtest/Makefile @@ -0,0 +1,12 @@ +CC=gcc +LD=$(CC) +SOURCES=memtest.c +OUTPUT=memtest +all: + $(CC) $(SOURCES) -o $(OUTPUT) + +debug: + $(CC) -g $(SOURCES) -o $(OUTPUT) + +clean: rm -rf *.o + rm -rf core* diff --git a/ndb/src/common/portlib/memtest/memtest.c b/ndb/src/common/portlib/memtest/memtest.c new file mode 100644 index 00000000000..d23235b7aa2 --- /dev/null +++ b/ndb/src/common/portlib/memtest/memtest.c @@ -0,0 +1,245 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + + +#include <stdio.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/mman.h> +long long getMilli(); +long long getMicro(); +void malloctest(int loopcount, int memsize, int touch); +void freetest(int loopcount, int memsize); +void mmaptest(int loopcount, int memsize, int touch); +void unmaptest(int loopcount, int memsize); + + +main(int argc, char ** argv) +{ + + int loopcount; + int memsize; + if(argc < 4) { + printf("Usage: memtest X loopcount memsize(MB)\n"); + printf("where X = \n"); + printf("1 : malloc test \n"); + printf("2 : mmap test \n"); + printf("3 : malloc test + touch pages\n"); + printf("4 : mmap test + touch pages\n"); + printf("5 : malloc/free test \n"); + printf("6 : mmap/munmap test \n"); + printf("loopcount - number of loops\n"); + printf("memsize - memory segment size to allocate in MB.\n"); + exit(1); + } + + + loopcount = atoi(argv[2]); + memsize = atoi(argv[3]); + switch(atoi(argv[1])) { + case 1: malloctest(loopcount, memsize , 0 ); + break; + case 2: mmaptest(loopcount, memsize,0); + break; + case 3: malloctest(loopcount, memsize,1); + break; + case 4: mmaptest(loopcount, memsize,1); + break; + case 5: freetest(loopcount, memsize); + break; + case 6: unmaptest(loopcount, memsize); + break; + default: + break; + } +} + +long long getMilli() { + struct timeval tick_time; + gettimeofday(&tick_time, 0); + + return + ((long long)tick_time.tv_sec) * ((long long)1000) + + ((long long)tick_time.tv_usec) / ((long long)1000); +} + +long long getMicro(){ + struct timeval tick_time; + int res = gettimeofday(&tick_time, 0); + + long long secs = tick_time.tv_sec; + long long micros = tick_time.tv_usec; + + micros = secs*1000000+micros; + return micros; +} + +void malloctest(int loopcount, int memsize, int touch) { + long long start=0; + int total=0; + int i=0, j=0; + int size=memsize*1024*1024; //bytes; + float mean; + char * ptr =0; + + printf("Staring malloctest "); + if(touch) + printf("with touch\n"); + else + printf("\n"); + + start=getMicro(); + + for(i=0; i<loopcount; i++){ + ptr=(char *)malloc((size_t)(size)); + if(ptr==0) { + printf("failed to malloc!\n"); + return; + } + if(touch) { + for(j=0; j<size; j=j+4096) + ptr[j]=1; + } + } + total=(int)(getMicro()-start); + + mean=(float)((float)total/(float)loopcount); + printf("Total time malloc %d bytes: %2.3f microsecs loopcount %d touch %d \n", + size, mean,loopcount, touch); +} + + +void mmaptest(int loopcount, int memsize, int touch) { + long long start=0; + int total=0; + int i=0, j=0; + char * ptr; + int size=memsize*1024*1024; //bytes; + float mean; + + printf("Staring mmaptest "); + if(touch) + printf("with touch \n"); + else + printf("\n"); + + start=getMicro(); + for(i=0; i<loopcount; i++){ + ptr = mmap(0, + size, + PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, + 0, + 0); + if(ptr<0) { + printf("failed to mmap!\n"); + return; + } + + if(touch) { + for(j=0; j<size; j=j+4096) + ptr[j]=1; + } + } + total=(int)(getMicro()-start); + mean=(float)((float)total/(float)loopcount); + printf("Total time mmap %d bytes: %2.3f microsecs \n",size, mean); +} + + +void unmaptest(loopcount, memsize) +{ + long long start=0; + int total=0; + int i=0, j=0; + char * ptr; + int size=memsize*1024*1024; //bytes; + float mean; + + printf("Staring munmap test (loopcount = 1 no matter what you prev. set)\n"); + + loopcount = 1; + + + for(i=0; i<loopcount; i++){ + ptr =(char*) mmap(0, + size, + PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, + 0, + 0); + if(ptr<0) { + printf("failed to mmap!\n"); + return; + } + + + for(j=0; j<size; j=j+1) + ptr[j]='1'; + start=getMicro(); + if(munmap(ptr, size)<0) { + printf("failed to munmap!\n"); + return; + } + + total=(int)(getMicro()-start); + /* + for(j=8192; j<size; j=j+4096) { + + *(ptr+j)='1'; + } + + for(j=0; j<4096; j=j+4096) { + *(ptr+j)='1'; + } + + */ + } + mean=(float)((float)total/(float)loopcount); + printf("Total time unmap %d bytes: %2.3f microsecs \n",size, mean); +} + +void freetest(int loopcount, int memsize) { + long long start=0; + int total=0; + int i=0, j=0; + int size=memsize*1024*1024; //bytes; + float mean; + char * ptr =0; + + loopcount = 1; + printf("Staring free test (loopcount = 1 no matter what you prev. set)\n"); + + + for(i=0; i<loopcount; i++){ + ptr=(char*)malloc((size_t)(size)); + if(ptr==0) { + printf("failed to malloc!\n"); + return; + } + for(j=0; j<size; j=j+4096) + ptr[j]='1'; + start=getMicro(); + free(ptr); + total=(int)(getMicro()-start); + } + + + mean=(float)((float)total/(float)loopcount); + printf("Total time free %d bytes: %2.3f microsecs loopcount %d \n", + size, mean,loopcount); +} diff --git a/ndb/src/common/portlib/memtest/munmaptest/Makefile b/ndb/src/common/portlib/memtest/munmaptest/Makefile new file mode 100644 index 00000000000..ea8c5238d1c --- /dev/null +++ b/ndb/src/common/portlib/memtest/munmaptest/Makefile @@ -0,0 +1,14 @@ +include .defs.mk + +TYPE := ndbapitest +BIN_TARGET := munmaptest + + +SOURCES = munmaptest.cpp + +include $(NDB_TOP)/Epilogue.mk + + + + + diff --git a/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp b/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp new file mode 100644 index 00000000000..9e396cd98ee --- /dev/null +++ b/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp @@ -0,0 +1,251 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + + + +#include <NdbOut.hpp> +#include <NdbThread.h> +#include <NdbMutex.h> +#include <NdbCondition.h> +#include <NdbSleep.h> +#include <NdbTick.h> +#include <NdbEnv.h> +#include <NdbHost.h> +#include <NdbMain.h> +#include <getarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/time.h> +#include <sys/mman.h> + + +struct ThreadData +{ + char * mapAddr; + Uint32 mapSize; + Uint32 chunk; + Uint32 idx; + +}; + +long long getMilli(); +long long getMicro(); + + +void* mapSegment(void * arg); +void* unmapSegment(void * arg); + + +void* mapSegment(void * arg) { + + ThreadData * threadArgs; + long long start=0; + int total=0; + int id = *(int *)arg; + threadArgs = new ThreadData [1]; + Uint32 size=5*1024*1024; + struct NdbThread* unmapthread_var; + void *status = 0; + int run = 1; + int max=0, min =100000000, sum=0; + while(run < 1001) { + start=getMicro(); + char * ptr =(char*) mmap(0, + size, + PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, + 0, + 0); + + total=(int)(getMicro()-start); + + ndbout << "T" << id << ": mmap took : " << total << " microsecs. " + << " Run: " << run ; + ndbout_c(" mapped @ %p \n", ptr); + + if(total>max) + max = total; + if(total<min) + min=total; + + sum+=total; + + if(ptr<0) { + ndbout << "failed to mmap!" << endl; + exit(1); + } + + + threadArgs[0].mapAddr = (char *)ptr; + threadArgs[0].mapSize = size; + threadArgs[0].chunk = 4096; + threadArgs[0].idx = 0; + + + for(Uint32 j=0; j<size; j=j+4096) + ptr[j]='1'; + + unmapthread_var = NdbThread_Create(unmapSegment, // Function + (void**)&threadArgs[0],// Arg + 32768, // Stacksize + (char*)"unmapthread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread prio + + + if(NdbThread_WaitFor(unmapthread_var, &status) != 0) { + ndbout << "test failed - exitting " << endl; + exit(1); + } + run++; + } + + ndbout << "MAX: " << max << " MIN: " << min; + float mean = (float) ((float)sum/(float)run); + ndbout_c(" AVERAGE: %2.5f\n",mean); +} + + + +void* unmapSegment(void * arg) +{ + + char * freeAddr; + char * mapAddr; + ThreadData * threadData = (ThreadData*) arg; + int start=0; + int total=0; + Uint32 mapSize = threadData->mapSize; + Uint32 chunk = threadData->chunk; + mapAddr = threadData->mapAddr; + + + + freeAddr = mapAddr+mapSize-chunk; + NdbSleep_MilliSleep(100); + for(Uint32 i=0;i<mapSize; i = i+chunk) { + start=getMicro(); + if(munmap(freeAddr, chunk) < 0){ + ndbout << "munmap failed" << endl; + exit(1); + } + total=(int)(getMicro()-start); + freeAddr = freeAddr - chunk; + NdbSleep_MilliSleep(10); + ndbout << "unmap 4096 bytes : " << total << "microsecs" << endl; + } + return NULL; +} + + +static int trash; +static int segmentsize=1; + + +static struct getargs args[] = { + { "trash", 't', arg_integer, &trash, + "trash the memory before (1 to trash 0 to not trash)", "trash"}, + { "segment", 's', arg_integer, &segmentsize, + "segment size (in MB)", "segment"}, +}; + + +static const int num_args = sizeof(args) / sizeof(args[0]); + +NDB_MAIN(munmaptest) { + + const char *progname = "munmaptest"; + int optind = 0; + + if(getarg(args, num_args, argc, argv, &optind)) { + arg_printusage(args, num_args, progname, ""); + exit(1); + } + + int size; + char * ptr; + if(trash) { + for(int i=0; i<100; i++) { + size=1+(int) (10.0*rand()/(RAND_MAX+1.0)); + NdbSleep_MilliSleep(10); + ptr =(char*) mmap(0, + size*1024*1024, + PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, + 0, + 0); + for(int i=0;i<(size*1024*1024); i=i+4096) { + *(ptr+i)='1'; + } + NdbSleep_MilliSleep(10); + + munmap(ptr,size); + + } + + + } + + int noThreads = 1; + struct NdbThread* mapthread_var; + int id[noThreads]; + void *status=0; + + ThreadData * threadArgs = new ThreadData[noThreads]; + + + + + for(int i=0; i < noThreads; i++) { + threadArgs[i].mapSize = segmentsize*1024*1024; + threadArgs[i].idx = i; + mapthread_var = NdbThread_Create(mapSegment, // Function + (void**)&threadArgs[i],// Arg + 32768, // Stacksize + (char*)"mapthread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread prio + + } + + + if(NdbThread_WaitFor(mapthread_var, &status) != 0) { + ndbout << "test failed - exitting " << endl; + exit(1); + } + +} + +long long getMilli() { + struct timeval tick_time; + gettimeofday(&tick_time, 0); + + return + ((long long)tick_time.tv_sec) * ((long long)1000) + + ((long long)tick_time.tv_usec) / ((long long)1000); +} + +long long getMicro(){ + struct timeval tick_time; + int res = gettimeofday(&tick_time, 0); + + long long secs = tick_time.tv_sec; + long long micros = tick_time.tv_usec; + + micros = secs*1000000+micros; + return micros; +} diff --git a/ndb/src/common/portlib/mmstest/mmslist.cpp b/ndb/src/common/portlib/mmstest/mmslist.cpp new file mode 100644 index 00000000000..bd00211445c --- /dev/null +++ b/ndb/src/common/portlib/mmstest/mmslist.cpp @@ -0,0 +1,103 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <NdbOut.hpp> +#include <NdbMain.h> + +#include <ose.h> +#include <mms.sig> +#include <mms_err.h> +#include <string.h> +#include <stdio.h> +#include <NdbOut.hpp> + +/** + * NOTE: To use NdbMem from a OSE system ose_mms has to be defined + * as a "Required External Process"(see OSE Kernel User's Guide/R1.1(p. 148)), + * like this: + * EXT_PROC(ose_mms, ose_mms, 50000) + * This will create a global variable ose_mms_ that is used from here. + */ + +union SIGNAL +{ + SIGSELECT sigNo; + struct MmsListDomainRequest mmsListDomainRequest; + struct MmsListDomainReply mmsListDomainReply; +}; /* union SIGNAL */ + +extern PROCESS ose_mms_; + +struct ARegion +{ + unsigned long int address; + unsigned long int size; + char name[32]; + + U32 resident; /* Boolean, nonzero if resident. */ + U32 access; /* See values for AccessType (above) .*/ + U32 type; /* either RAM-mem (1) or Io-mem (2) */ + U32 cache; /* 0-copyback,1-writethrough, 2-CacheInhibit.*/ +}; + +NDB_COMMAND(mmslist, "mmslist", "mmslist", "LIst the MMS memory segments", 4096){ + if (argc == 1){ + + static SIGSELECT allocate_sig[] = {1,MMS_LIST_DOMAIN_REPLY}; + union SIGNAL *sig; + + /* Send request to list all segments and regions. */ + sig = alloc(sizeof(struct MmsListDomainRequest), + MMS_LIST_DOMAIN_REQUEST); + send(&sig, ose_mms_); + + while (true){ + sig = receive(allocate_sig); + if (sig != NIL){ + if (sig->mmsListDomainReply.status == MMS_SUCCESS){ + /* Print domain info */ + ndbout << "=================================" << endl; + ndbout << "domain: " << sig->mmsListDomainReply.domain << endl; + ndbout << "name : " << sig->mmsListDomainReply.name << endl; + ndbout << "used : " << sig->mmsListDomainReply.used << endl; + ndbout << "lock : " << sig->mmsListDomainReply.lock << endl; + ndbout << "numOfRegions:" << sig->mmsListDomainReply.numOfRegions << endl; + struct ARegion * tmp = (struct ARegion*)&sig->mmsListDomainReply.regions[0]; + for (int i = 0; i < sig->mmsListDomainReply.numOfRegions && i < 256; i++){ + ndbout << i << ": adress=" << tmp->address << + ", size=" << tmp->size << + ", name=" << tmp->name << + ", resident=" << tmp->resident << + ", access=" << tmp->access << + ", type=" << tmp->type << + ", cache=" << tmp->cache << endl; + tmp++; + } + + free_buf(&sig); + }else{ + free_buf(&sig); + break; + } + } + + } + + }else{ + ndbout << "Usage: mmslist" << endl; + } + return NULL; +} diff --git a/ndb/src/common/portlib/mmstest/mmstest.cpp b/ndb/src/common/portlib/mmstest/mmstest.cpp new file mode 100644 index 00000000000..6ebb5064aaf --- /dev/null +++ b/ndb/src/common/portlib/mmstest/mmstest.cpp @@ -0,0 +1,76 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <NdbOut.hpp> +#include "NdbThread.h" +#include <NdbMem.h> +#include <NdbMain.h> + +#include <stdlib.h> + +NDB_COMMAND(ndbmem, "ndbmem", "ndbmem", "Test the ndbmem functionality", 4096){ + + ndbout << "Starting test of NdbMem" << endl; + ndbout << "=======================" << endl; + + ndbout << "Creating NdbMem" << endl; + NdbMem_Create(); + + + ndbout << "NdbMem - test 1" << endl; + if (argc == 2){ + int size1 = atoi(argv[1]); + ndbout << "Allocate and test "<<size1<<" bytes of memory" << endl; + char* mem1 = (char*)NdbMem_Allocate(size1); + ndbout << "mem1 = " << hex << (int)mem1 << endl; + if (mem1 != NULL){ + char* p1; + + // Write to the memory allocated + p1 = mem1; + for(int i = 0; i < size1; i++){ + *p1 = (char)(i%256); + p1++; + } + + // Read from the memory and check value + char read1; + char* pread1; + pread1 = mem1; + for(int i = 0; i < size1; i++){ + read1 = *pread1; + //ndbout << i << "=" << read1 << endl; + if (read1 != (i%256)) + ndbout << "Byte " << i << " was not correct, read1=" << read1 << endl; + pread1++; + } + + ndbout << "Freeing NdbMem" << endl; + NdbMem_Free(mem1); + } + + ndbout << "Destroying NdbMem" << endl; + NdbMem_Destroy(); + }else{ + ndbout << "Usage: ndbmem <size(bytes)>"<< endl; + } + + return NULL; + +} + + + diff --git a/ndb/src/common/portlib/ose/Makefile b/ndb/src/common/portlib/ose/Makefile new file mode 100644 index 00000000000..4ef93b7824a --- /dev/null +++ b/ndb/src/common/portlib/ose/Makefile @@ -0,0 +1,31 @@ +include .defs.mk + +TYPE := + +PIC_ARCHIVE := Y +ARCHIVE_TARGET := portlib + +SOURCES = NdbOut.cpp + +SOURCES.c = NdbCondition.c \ + NdbMutex.c \ + NdbSleep.c \ + NdbTick.c \ + NdbEnv.c \ + NdbThread.c \ + NdbHost.c \ + NdbTCP.c + +ifeq ($(NDB_OS), SOFTOSE) + SOURCES += NdbMem_SoftOse.cpp +else + SOURCES.c += NdbMem.c +endif + +include $(NDB_TOP)/Epilogue.mk + + + + + + diff --git a/ndb/src/common/portlib/ose/NdbCondition.c b/ndb/src/common/portlib/ose/NdbCondition.c new file mode 100644 index 00000000000..2ab6e49006b --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbCondition.c @@ -0,0 +1,244 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbCondition.h" +#include <pthread.h> +#include <assert.h> +#include <sys/types.h> +#include <malloc.h> + +#include <NdbMutex.h> + +#include "NdbConditionOSE.h" +struct NdbCondition +{ + PROCESS condserv_pid; +}; + + +OS_PROCESS(ndbcond_serv){ + + union SIGNAL* sig; + union SIGNAL* sig2; + + static const SIGSELECT sel_signal[] = {2, NDBCOND_SIGNAL, NDBCOND_BROADCAST}; + static const SIGSELECT sel_cond[] = {2, NDBCOND_WAIT, NDBCOND_WAITTIMEOUT}; + + for(;;){ + /* Receive condition wait signal */ + sig = receive((SIGSELECT*)sel_cond); + if (sig != NIL){ + switch (sig->sigNo){ + + case NDBCOND_WAIT: + /* Wait for a SIGNAL or BROADCAST from anyone */ + sig2 = receive((SIGSELECT*)sel_signal); + if (sig2 != NIL){ + switch(sig2->sigNo){ + + case NDBCOND_SIGNAL: + ((struct NdbCondWait*)sig)->status = NDBCOND_SIGNALED; + /* Send signal back to the one waiting for this condition */ + send(&sig, sender(&sig)); + break; + case NDBCOND_BROADCAST: + /* Not handled yet */ + assert(1==0); + break; + default: + assert(1==0); + break; + } + free_buf(&sig2); + } + break; + + case NDBCOND_WAITTIMEOUT: + /* Wait for a SIGNAL or BROADCAST from anyone */ + sig2 = receive_w_tmo(((struct NdbCondWaitTimeout*)sig)->timeout, (SIGSELECT*)sel_signal); + if (sig2 != NIL){ + switch(sig2->sigNo){ + + case NDBCOND_SIGNAL: + ((struct NdbCondWaitTimeout*)sig)->status = NDBCOND_SIGNALED; + /* Send signal back to the one waiting for this condition */ + send(&sig, sender(&sig)); + break; + case NDBCOND_BROADCAST: + /* Not handled yet */ + assert(1==0); + break; + default: + assert(1==0); + break; + } + free_buf(&sig2); + }else{ + ((struct NdbCondWaitTimeout*)sig)->status = NDBCOND_TIMEOUT; + send(&sig, sender(&sig)); + } + break; + + default: + assert(1==0); + break; + + } + } + + } +} + + +struct NdbCondition* +NdbCondition_Create(void) +{ + struct NdbCondition* tmpCond; + + + tmpCond = (struct NdbCondition*)malloc(sizeof(struct NdbCondition)); + + if (tmpCond == NULL) + return NULL; + + /** + * Start this process with a quite high + * priority, we want it to be responsive + */ + tmpCond->condserv_pid = create_process(OS_PRI_PROC, /* Process type */ + "ndbcond_serv", /* Name */ + ndbcond_serv, /* Entry point */ + 2048, /* Stack size */ + 10, /* Priority */ + 0, /* Time slice */ + get_bid(current_process()), /* Block */ + NULL, /* Redir table */ + 0, + 0); + + start(tmpCond->condserv_pid); + + return tmpCond; +} + + +int +NdbCondition_Wait(struct NdbCondition* p_cond, + NdbMutex* p_mutex) +{ + static const SIGSELECT sel_cond[] = {1, NDBCOND_WAIT}; + union SIGNAL* sig; + int result; + if (p_cond == NULL || p_mutex == NULL) + return 0; + + sig = alloc(sizeof(struct NdbCondWait), NDBCOND_WAIT); + send(&sig, p_cond->condserv_pid); + + NdbMutex_Unlock(p_mutex); + + result = 1; + while(NIL == (sig = receive_from((OSTIME)-1, (SIGSELECT*)sel_cond, p_cond->condserv_pid))); + if (sig != NIL){ + if (sig->sigNo == NDBCOND_WAIT){ + /* Condition is signaled */ + result = 0; + }else{ + assert(1==0); + } + free_buf(&sig); + + } + NdbMutex_Lock(p_mutex); + + return result; +} + + +int +NdbCondition_WaitTimeout(struct NdbCondition* p_cond, + NdbMutex* p_mutex, + int msecs){ + static const SIGSELECT sel_cond[] = {1, NDBCOND_WAITTIMEOUT}; + union SIGNAL* sig; + int result; + if (p_cond == NULL || p_mutex == NULL) + return 0; + + sig = alloc(sizeof(struct NdbCondWaitTimeout), NDBCOND_WAITTIMEOUT); + ((struct NdbCondWaitTimeout*)sig)->timeout = msecs; + send(&sig, p_cond->condserv_pid); + + NdbMutex_Unlock(p_mutex); + + result = 1; + while(NIL == (sig = receive_from((OSTIME)-1, (SIGSELECT*)sel_cond, p_cond->condserv_pid))); + if (sig != NIL){ + if (sig->sigNo == NDBCOND_WAITTIMEOUT){ + /* Condition is signaled */ + result = 0; + }else{ + assert(1==0); + } + free_buf(&sig); + + } + + NdbMutex_Lock(p_mutex); + + return result; +} + + +int +NdbCondition_Signal(struct NdbCondition* p_cond){ + + union SIGNAL* sig; + if (p_cond == NULL) + return 1; + + sig = alloc(sizeof(struct NdbCondSignal), NDBCOND_SIGNAL); + send(&sig, p_cond->condserv_pid); + + return 0; +} + + +int NdbCondition_Broadcast(struct NdbCondition* p_cond) +{ + union SIGNAL* sig; + if (p_cond == NULL) + return 1; + + sig = alloc(sizeof(struct NdbCondBroadcast), NDBCOND_BROADCAST); + send(&sig, p_cond->condserv_pid); + + return 0; +} + + +int NdbCondition_Destroy(struct NdbCondition* p_cond) +{ + if (p_cond == NULL) + return 1; + + kill_proc(p_cond->condserv_pid); + free(p_cond); + + return 0; +} + diff --git a/ndb/src/common/portlib/ose/NdbConditionOSE.h b/ndb/src/common/portlib/ose/NdbConditionOSE.h new file mode 100644 index 00000000000..bd0306261cc --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbConditionOSE.h @@ -0,0 +1,103 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef NDB_CONDITIONOSE_H +#define NDB_CONDITIONOSE_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NDBCOND_SIGBASE 4000 + +#define NDBCOND_WAIT (NDBCOND_SIGBASE + 1) /* !-SIGNO(struct NdbCondWait)-! */ +#define NDBCOND_WAITTIMEOUT (NDBCOND_SIGBASE + 2) /* !-SIGNO(struct NdbCondWaitTimeOut)-! */ +#define NDBCOND_SIGNAL (NDBCOND_SIGBASE + 3) /* !-SIGNO(struct NdbCondSignal)-! */ +#define NDBCOND_BROADCAST (NDBCOND_SIGBASE + 4) /* !-SIGNO(struct NdbCondBroadcast)-! */ + + +const char * +sigNo2String(SIGSELECT sigNo){ + switch(sigNo){ + case NDBCOND_WAIT: + return "NDBCOND_WAIT"; + break; + case NDBCOND_WAITTIMEOUT: + return "NDBCOND_WAITTIMEOUT"; + break; + case NDBCOND_SIGNAL: + return "NDBCOND_SIGNAL"; + break; + case NDBCOND_BROADCAST: + return "NDBCOND_BROADCAST"; + break; + } + return "UNKNOWN"; +} + +struct NdbCondWait +{ + SIGSELECT sigNo; + int status; +}; + +/** + * Signal received + */ +#define NDBCOND_SIGNALED 1 + +/** + * Timeout occured + */ +#define NDBCOND_TIMEOUT 2 + +struct NdbCondWaitTimeout +{ + SIGSELECT sigNo; + int timeout; + int status; + +}; + +struct NdbCondSignal +{ + SIGSELECT sigNo; +}; + +struct NdbCondBroadcast +{ + SIGSELECT sigNo; +}; + + +union SIGNAL +{ + SIGSELECT sigNo; + struct NdbCondWait condWait; + struct NdbCondWaitTimeout condWaitTimeout; + struct NdbCondSignal condSignal; + struct NdbCondBroadcast condBroadcast; +}; + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ndb/src/common/portlib/ose/NdbEnv.c b/ndb/src/common/portlib/ose/NdbEnv.c new file mode 100644 index 00000000000..e2ac4d879d2 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbEnv.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbEnv.h" +#include <string.h> +#include <stdlib.h> + +const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen) +{ + /** + * All environment variables are associated with a process + * it's important to read env from the correct process + * for now read from own process, own block and last the "ose_shell" process. + * + * TODO! What process should this be read from in the future? + * + */ + PROCESS proc_; + char* p = NULL; + /* Look in own process */ + p = get_env(current_process(), (char*)name); + if (p == NULL){ + /* Look in block process */ + p = get_env(get_bid(current_process()), (char*)name); + if (p == NULL){ + /* Look in ose_shell process */ + if (hunt("ose_shell", 0, &proc_, NULL)){ + p = get_env(proc_, (char*)name); + } + } + } + + if (p != NULL){ + strncpy(buf, p, buflen); + buf[buflen-1] = 0; + free_buf((union SIGNAL **)&p); + p = buf; + } + return p; +} + diff --git a/ndb/src/common/portlib/ose/NdbHost.c b/ndb/src/common/portlib/ose/NdbHost.c new file mode 100644 index 00000000000..f5e1e511c16 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbHost.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbHost.h" +#include <unistd.h> + + +#include <inet.sig> +#include <string.h> + +union SIGNAL +{ + SIGSELECT sigNo; + struct InetIfUp inetIfUp; +}; + +int NdbHost_GetHostName(char* buf) +{ +#if 0 + extern PROCESS ose_inet_; + union SIGNAL *signal; + static const SIGSELECT select_if_up_reply[] = { 1, INET_IF_UP_REPLY }; + + signal = alloc(sizeof(struct InetIfUp), INET_IF_UP_REQUEST); + strcpy(signal->inetIfUp.ifName, "*"); + send((union SIGNAL **)&signal, ose_inet_); + signal = receive((SIGSELECT *)select_if_up_reply); + strcpy(buf, signal->inetIfUp.ifName); + free_buf(&signal); + return 0; +#else + return -1; +#endif +} + + +int NdbHost_GetProcessId(void) +{ + return current_process(); +} + diff --git a/ndb/src/common/portlib/ose/NdbMem.c b/ndb/src/common/portlib/ose/NdbMem.c new file mode 100644 index 00000000000..6d922e4c073 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbMem.c @@ -0,0 +1,183 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbMem.h" + +#include <assert.h> + +#if defined NDB_OSE +#include <ose.h> +#include <mms.sig> +#include <mms_err.h> +#include <string.h> +#include <stdio.h> +#include <NdbOut.hpp> + +// Page size for mp750 is 4096 bytes. +#define PAGE_SIZE 4096 + +/** + * NOTE: To use NdbMem from a OSE system ose_mms has to be defined + * as a "Required External Process"(see OSE Kernel User's Guide/R1.1(p. 148)), + * like this in osemain.con: + * EXT_PROC(ose_mms, ose_mms, 50000) + * This will create a global variable ose_mms_ that is used from here. + */ + +union SIGNAL +{ + SIGSELECT sigNo; + struct MmsAllocateRegionRequest mmsAllocateRegionRequest; + struct MmsAllocateRegionReply mmsAllocateRegionReply; + struct MmsFreeRegionRequest mmsFreeRegionRequest; + struct MmsFreeRegionReply mmsFreeRegionReply; +}; /* union SIGNAL */ + +extern PROCESS ose_mms_; + +void NdbMem_Create(void) +{ + /* Do nothing */ + return; +} + +void NdbMem_Destroy(void) +{ + /* Do nothing */ + return; +} + +void* NdbMem_Allocate(size_t size) +{ + static SIGSELECT allocate_sig[] = {1,MMS_ALLOCATE_REGION_REPLY}; + union SIGNAL *sig; + U32 allocatedAdress; + + assert(size > 0); + + // Only allowed to allocate multiples of the page size. + if(size % PAGE_SIZE != 0) { + size += PAGE_SIZE - size%PAGE_SIZE; + } + + /* Allocate a new region in the callers memory segment. */ + sig = alloc(sizeof(struct MmsAllocateRegionRequest), + MMS_ALLOCATE_REGION_REQUEST); + /* -1: The callers domain is used */ + sig->mmsAllocateRegionRequest.domain = (MemoryDomain)-1; + sig->mmsAllocateRegionRequest.useAddr = False; + sig->mmsAllocateRegionRequest.size = size; + sig->mmsAllocateRegionRequest.access = SuperRW_UserRW; + sig->mmsAllocateRegionRequest.resident = False; + sig->mmsAllocateRegionRequest.memory = CodeData; + sig->mmsAllocateRegionRequest.cache = CopyBack; + strcpy(sig->mmsAllocateRegionRequest.name, "NDB_DATA"); + send(&sig, ose_mms_); + sig = receive(allocate_sig); + + if (sig->mmsAllocateRegionReply.status != MMS_SUCCESS){ + /* Memory allocation failed, make sure this function returns NULL */ + allocatedAdress = NULL; + } + else{ + allocatedAdress = sig->mmsAllocateRegionReply.address; + } + free_buf(&sig); + return (void*)allocatedAdress; +} + +void* NdbMem_AllocateAlign(size_t size, size_t alignment) +{ + return NdbMem_Allocate(size); +} + + +void NdbMem_Free(void* ptr) +{ + static SIGSELECT free_sig[] = {1,MMS_FREE_REGION_REPLY}; + union SIGNAL *sig; + + /* Free a region in the callers domain. */ + sig = alloc(sizeof(struct MmsFreeRegionRequest), + MMS_FREE_REGION_REQUEST); + sig->mmsFreeRegionRequest.address = (U32)ptr; + send(&sig, ose_mms_); + sig = receive(free_sig); + + if (sig->mmsFreeRegionReply.status != MMS_SUCCESS){ + ndbout_c("The MMS Region could not be deallocated.\r\n"); + error(sig->mmsFreeRegionReply.status); + }; + free_buf(&sig); +} + +int NdbMem_MemLockAll(){ + return -1; +} + +int NdbMem_MemUnlockAll(){ + return -1; +} + +#else +#include <assert.h> +#include <stdlib.h> + + +void NdbMem_Create() +{ + /* Do nothing */ + return; +} + +void NdbMem_Destroy() +{ + /* Do nothing */ + return; +} + +void* NdbMem_Allocate(size_t size) +{ + assert(size > 0); + return (void*)malloc(size); +} + +void* NdbMem_AllocateAlign(size_t size, size_t alignment) +{ + /* + return (void*)memalign(alignment, size); + TEMP fix + */ + return (void*)malloc(size); +} + + +void NdbMem_Free(void* ptr) +{ + free(ptr); +} + + +int NdbMem_MemLockAll(){ + return -1; +} + +int NdbMem_MemUnlockAll(){ + return -1; +} + +#endif diff --git a/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp b/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp new file mode 100644 index 00000000000..cad22c0474b --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp @@ -0,0 +1,53 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "NdbMem.h" + +extern "C" +void NdbMem_Create() +{ +} +extern "C" +void NdbMem_Destroy() +{ +} + +extern "C" +void* NdbMem_Allocate(size_t size) +{ + return new char[size]; +} + +extern "C" +void* NdbMem_AllocateAlign(size_t size, size_t alignment) +{ + return NdbMem_Allocate(size); +} + +extern "C" +void NdbMem_Free(void* ptr) +{ + delete [] (char *)(ptr); +} + +int NdbMem_MemLockAll(){ + return -1; +} + +int NdbMem_MemUnlockAll(){ + return -1; +} + diff --git a/ndb/src/common/portlib/ose/NdbMutex.c b/ndb/src/common/portlib/ose/NdbMutex.c new file mode 100644 index 00000000000..859ddefd536 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbMutex.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbMutex.h" + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> + + +NdbMutex* NdbMutex_Create(void) +{ + NdbMutex* pNdbMutex; + + pNdbMutex = create_sem(1); + + return pNdbMutex; +} + + +int NdbMutex_Destroy(NdbMutex* p_mutex) +{ + + if (p_mutex == NULL) + return -1; + + kill_sem(p_mutex); + + return 0; + +} + + +int NdbMutex_Lock(NdbMutex* p_mutex) +{ + if (p_mutex == NULL) + return -1; + + wait_sem(p_mutex); + + return 0; +} + + +int NdbMutex_Unlock(NdbMutex* p_mutex) +{ + + if (p_mutex == NULL) + return -1; + + signal_sem(p_mutex); + + return 0; +} + + +int NdbMutex_Trylock(NdbMutex* p_mutex) +{ + int result = -1; + + if (p_mutex != NULL) { + OSSEMVAL semvalue = get_sem(p_mutex); + if (semvalue > 0) { + wait_sem(p_mutex); + result = 0; + } + } + + return result; + +} + diff --git a/ndb/src/common/portlib/ose/NdbOut.cpp b/ndb/src/common/portlib/ose/NdbOut.cpp new file mode 100644 index 00000000000..0ee12249ff5 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbOut.cpp @@ -0,0 +1,99 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "NdbOut.hpp" +#include <NdbStdio.h> +#include <stdarg.h> +#include <NdbUnistd.h> +#include <string.h> + + +#if defined NDB_SOFTOSE +#include <dbgprintf.h> +#define printfunc dbgprintf +#else +#define printfunc printf +#endif + +static char const* const endlineString = "\r\n"; + +static int CtrlC = 0; +NdbOut ndbout; + + +NdbOut& NdbOut::operator<<(int aVal) +{ + char* format; + char HexFormat[] = "0x%08x"; + char DecFormat[] = "%d"; + if (isHexFormat == 1) + format = HexFormat; + else + format = DecFormat; + + printfunc(format, aVal); + return *this; +} + +NdbOut& NdbOut::operator<<(char* pVal) +{ + printfunc("%s", pVal); + return *this; +} + +NdbOut& NdbOut::endline() +{ + isHexFormat = 0; // Reset hex to normal, if user forgot this + printfunc(endlineString); + return *this; +} + +NdbOut& NdbOut::flushline() +{ + isHexFormat = 0; // Reset hex to normal, if user forgot this + return *this; +} + +NdbOut& NdbOut::setHexFormat(int _format) +{ + isHexFormat = _format; + return *this; +} + +NdbOut::NdbOut() +{ + CtrlC = 0; + isHexFormat = 0; +} + +NdbOut::~NdbOut() +{ +} + + + +extern "C" +void +ndbout_c(const char * fmt, ...){ + va_list ap; + char buf[1000]; + + va_start(ap, fmt); + if (fmt != 0) + vsnprintf(buf, sizeof(buf)-1, fmt, ap); + ndbout << buf << endl; + va_end(ap); +} diff --git a/ndb/src/common/portlib/ose/NdbSleep.c b/ndb/src/common/portlib/ose/NdbSleep.c new file mode 100644 index 00000000000..70fd83117ef --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbSleep.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbSleep.h" + +#include <ose.h> + + +int +NdbSleep_MilliSleep(int milliseconds){ + const OSTIME millisecond_delay = milliseconds; + delay(millisecond_delay); + return 0; +} + +int +NdbSleep_SecSleep(int seconds){ + const OSTIME millisecond_delay = seconds*1000; + delay(millisecond_delay); + return 0; +} + diff --git a/ndb/src/common/portlib/ose/NdbTCP.c b/ndb/src/common/portlib/ose/NdbTCP.c new file mode 100644 index 00000000000..9994697b3f8 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbTCP.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbTCP.h" + + +int +Ndb_getInAddr(struct in_addr * dst, const char *address) { + struct hostent * host; + host = gethostbyname_r(address); + if(host != 0){ + dst->s_addr = ((struct in_addr *) *host->h_addr_list)->s_addr; + free_buf((union SIGNAL **)&host); + return 0; + } + /* Try it as aaa.bbb.ccc.ddd. */ + dst->s_addr = inet_addr(address); + if (dst->s_addr != INADDR_NONE) { + return 0; + } + return -1; +} + + diff --git a/ndb/src/common/portlib/ose/NdbThread.c b/ndb/src/common/portlib/ose/NdbThread.c new file mode 100644 index 00000000000..41a5f181c40 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbThread.c @@ -0,0 +1,184 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbThread.h" +#include <pthread.h> +#include <malloc.h> +#include <assert.h> +#include <string.h> +#include <NdbOut.hpp> + +#define MAX_THREAD_NAME 16 + + +struct NdbThread +{ + PROCESS pid; + char thread_name[MAX_THREAD_NAME]; +}; + +#define NDBTHREAD_SIGBASE 4010 + +#define NDBTHREAD_START (NDBTHREAD_SIGBASE + 1) /* !-SIGNO(struct NdbThreadStart)-! */ + +struct NdbThreadStart +{ + SIGSELECT sigNo; + NDB_THREAD_FUNC* func; + NDB_THREAD_ARG arg; +}; + +struct NdbThreadStopped +{ + SIGSELECT sigNo; +}; + +union SIGNAL +{ + SIGSELECT sigNo; + struct NdbThreadStart threadStart; + struct NdbThreadStopped threadStopped; +}; + +OS_PROCESS(thread_starter){ + static const SIGSELECT sel_start[] = {1, NDBTHREAD_START}; + struct NdbThreadStart* sigstart; + union SIGNAL* sig; + + /* Receive function adress and params */ + sig = receive((SIGSELECT*)sel_start); + if (sig != NIL){ + if (sig->sigNo == NDBTHREAD_START){ + sigstart = ((struct NdbThreadStart*)sig); + /* Execute function with arg */ + (*sigstart->func)(sigstart->arg); + }else{ + assert(1==0); + } + free_buf(&sig); + } +} + +struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC* p_thread_func, + NDB_THREAD_ARG *p_thread_arg, + const NDB_THREAD_STACKSIZE thread_stack_size, + const char* p_thread_name, + NDB_THREAD_PRIO thread_prio) +{ + struct NdbThread* tmpThread; + union SIGNAL* sig; + int ose_prio; + + if (p_thread_func == NULL) + return 0; + + tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread)); + if (tmpThread == NULL) + return NULL; + + strncpy((char*)&tmpThread->thread_name, p_thread_name, MAX_THREAD_NAME); + + switch(thread_prio){ + case NDB_THREAD_PRIO_HIGHEST: + ose_prio = 1; + break; + case NDB_THREAD_PRIO_HIGH: + ose_prio = 10; + break; + case NDB_THREAD_PRIO_MEAN: + ose_prio = 16; + break; + case NDB_THREAD_PRIO_LOW: + ose_prio = 23; + break; + case NDB_THREAD_PRIO_LOWEST: + ose_prio = 31; + break; + default: + return NULL; + break; + } + + /* Create process */ + tmpThread->pid = create_process(OS_PRI_PROC, /* Process type */ + (char*)p_thread_name, /* Name */ + thread_starter, /* Entry point */ + thread_stack_size, /* Stack size */ + ose_prio, /* Priority */ + 0, /* Time slice */ + get_bid(current_process()), /* Block */ + NULL, /* Redir table */ + 0, + 0); + + /* Send params to process */ + sig = alloc(sizeof(struct NdbThreadStart), NDBTHREAD_START); + ((struct NdbThreadStart*)sig)->func = p_thread_func; + ((struct NdbThreadStart*)sig)->arg = p_thread_arg; + send(&sig, tmpThread->pid); + + /* Enable NDB_HOME environment variable for the thread */ + { + /* Hardcoded NDB_HOME...*/ + char* ndb_home_env = get_env(current_process(), "NDB_HOME"); + if (ndb_home_env != NULL) + { + /* Set NDB_HOME */ + int rc = set_env(tmpThread->pid, "NDB_HOME", ndb_home_env); + if (rc != 0) + { + /* Not really a problem */ + } + } /* Enable NDB_HOME */ + } + + /* Start process */ + start(tmpThread->pid); + + return tmpThread; +} + + + +void NdbThread_Destroy(struct NdbThread** p_thread) +{ + free(* p_thread); * p_thread = 0; +} + + +int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status) +{ + while(hunt(p_wait_thread->thread_name, 0, NULL, NULL) != 0) + delay(1000); + + * status = 0; + + return 0; +} + + +void NdbThread_Exit(int a) +{ + kill_proc(current_process()); +} + + +int NdbThread_SetConcurrencyLevel(int level) +{ + return 0; +} + diff --git a/ndb/src/common/portlib/ose/NdbTick.c b/ndb/src/common/portlib/ose/NdbTick.c new file mode 100644 index 00000000000..c3deae2bec3 --- /dev/null +++ b/ndb/src/common/portlib/ose/NdbTick.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbTick.h" +#include <time.h> + +#define NANOSEC_PER_SEC 1000000000 +#define MICROSEC_PER_SEC 1000000 +#define MILLISEC_PER_SEC 1000 +#define MICROSEC_PER_MILLISEC 1000 +#define MILLISEC_PER_NANOSEC 1000000 + +#ifdef NDB_OSE +NDB_TICKS NdbTick_CurrentMillisecond(void) +{ + return get_ticks()*4; +} +#include <rtc.h> +int +NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){ + struct TimePair tvp; + rtc_get_time(&tvp); + * secs = tvp.seconds; + * micros = tvp.micros; + return 0; +} + +#endif + +#if defined NDB_SOFTOSE +NDB_TICKS NdbTick_CurrentMillisecond(void) +{ + /** + * Depends on the interval counter in solaris + * that means each "tick" in OSE is really 10 milliseconds + */ + return get_ticks()*10; +} + +#include <rtc.h> +int +NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){ + struct TimePair tvp; + rtc_get_time(&tvp); + * secs = tvp.seconds; + * micros = tvp.micros; + return 0; +} +#endif + diff --git a/ndb/src/common/portlib/test/Makefile b/ndb/src/common/portlib/test/Makefile new file mode 100644 index 00000000000..4edc98ede75 --- /dev/null +++ b/ndb/src/common/portlib/test/Makefile @@ -0,0 +1,15 @@ +include .defs.mk + +TYPE := kernel + +BIN_TARGET := PortLibTest +BIN_TARGET_ARCHIVES := portlib general + +SOURCES = NdbPortLibTest.cpp + +include $(NDB_TOP)/Epilogue.mk + + + + + diff --git a/ndb/src/common/portlib/test/NdbPortLibTest.cpp b/ndb/src/common/portlib/test/NdbPortLibTest.cpp new file mode 100644 index 00000000000..8a5c8f4a878 --- /dev/null +++ b/ndb/src/common/portlib/test/NdbPortLibTest.cpp @@ -0,0 +1,621 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + * NdbPortLibTest.cpp + * Test the functionality of portlib + * TODO - Add tests for NdbMem + */ + + + +#include "NdbOut.hpp" +#include "NdbThread.h" +#include "NdbMutex.h" +#include "NdbCondition.h" +#include "NdbSleep.h" +#include "NdbTick.h" +#include "NdbEnv.h" +#include "NdbHost.h" +#include "NdbMain.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +int TestHasFailed; +int verbose = 0; + +static void fail(const char* test, const char* cause) +{ + TestHasFailed = 1; + ndbout << test << " failed, " << cause << endl; +} + +// test 1 variables and funcs + +extern "C" void* thread1func(void* arg) +{ + int arg1; + int returnvalue = 8; + arg1 = *(int*)arg; + ndbout << "thread1: thread1func called with arg = " << arg1 << endl; + + // delay(1000); + if (arg1 != 7) + fail("TEST1", "Wrong arg"); + + NdbThread_Exit(returnvalue); + + return NULL; + +} + +// test 2 variables and funcs + +NdbMutex* test2mutex; + +extern "C" void* test2func(void* arg) +{ + + int arg1; + arg1 = *(int*)arg; + ndbout << "thread" << arg1 << " started in test2func" << endl; + + if (NdbMutex_Lock(test2mutex) != 0) + fail("TEST2", "Failed to lock mutex"); + + ndbout << "thread" << arg1 << ", test2func " << endl; + + if (NdbMutex_Unlock(test2mutex) != 0) + fail("TEST2", "Failed to unlock mutex"); + + int returnvalue = arg1; + NdbThread_Exit(returnvalue); + + return NULL; + +} + + +// test 3 and 7 variables and funcs + +NdbMutex* testmutex; +NdbCondition* testcond; +int testthreadsdone; + +extern "C" void* testfunc(void* arg) +{ + int tmpVar; + int threadno; + int result; + + threadno = *(int*)arg; + + ndbout << "Thread" << threadno << " started in testfunc" << endl; + do + { + + if ((threadno % 2) == 0) + result = NdbSleep_SecSleep(1); + else + result = NdbSleep_MilliSleep(100); + + if (result != 0) + fail("TEST3", "Wrong result from sleep function"); + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST3", "Wrong result from NdbMutex_Lock function"); + + ndbout << "thread" << threadno << ", testfunc " << endl; + testthreadsdone++; + tmpVar = testthreadsdone; + + if (NdbCondition_Signal(testcond) != 0) + fail("TEST3", "Wrong result from NdbCondition_Signal function"); + + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST3", "Wrong result from NdbMutex_Unlock function"); + + } + while(tmpVar<100); + + NdbThread_Exit(0); + return NULL; +} + +extern "C" void* testTryLockfunc(void* arg) +{ + int tmpVar = 0; + int threadno; + int result; + + threadno = *(int*)arg; + + ndbout << "Thread" << threadno << " started" << endl; + do + { + + if ((threadno % 2) == 0) + result = NdbSleep_SecSleep(1); + else + result = NdbSleep_MilliSleep(100); + + if (result != 0) + fail("TEST3", "Wrong result from sleep function"); + + if (NdbMutex_Trylock(testmutex) == 0){ + + ndbout << "thread" << threadno << ", testTryLockfunc locked" << endl; + testthreadsdone++; + tmpVar = testthreadsdone; + + if (NdbCondition_Signal(testcond) != 0) + fail("TEST3", "Wrong result from NdbCondition_Signal function"); + + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST3", "Wrong result from NdbMutex_Unlock function"); + } + + } + while(tmpVar<100); + + NdbThread_Exit(0); + return NULL; +} + + + +void testMicros(int count); +Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2); + +NDB_COMMAND(PortLibTest, "portlibtest", "portlibtest", "Test the portable function layer", 4096){ + + ndbout << "= TESTING ARGUMENT PASSING ============" << endl; + ndbout << "ARGC: " << argc << endl; + for(int i = 1; i < argc; i++){ + ndbout << " ARGV"<<i<<": " << (char*)argv[i] << endl; + } + ndbout << endl << endl; + + + struct NdbThread* thread1var; + void *status = 0; + int arg = 7; + + TestHasFailed = 0; + // create one thread and wait for it to return + ndbout << "= TEST1 ===============================" << endl; + + thread1var = NdbThread_Create(thread1func, // Function + (void**)&arg,// Arg + 2048, // Stacksize + (char*)"thread1", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + + + if(NdbThread_WaitFor(thread1var, &status) != 0) + fail("TEST1", "NdbThread_WaitFor failed"); + // NOTE! thread return value is not yet used in Ndb and thus not tested(does not work) + //ndbout << "thread1 returned, status = " << status << endl; + //if (status != 8) + // fail("TEST1", "Wrong status"); + ndbout << "TEST1 completed" << endl; + + + NdbThread_Destroy(&thread1var); + + // Create 10 threads that will wait for a mutex before printing it's message to screen + ndbout << "= TEST2 ===============================" << endl; +#define T2_THREADS 10 + NdbThread* threads[T2_THREADS]; + int args[T2_THREADS]; + void *status2 = 0; + test2mutex = NdbMutex_Create(); + NdbMutex_Lock(test2mutex); + + for (int i = 0; i < T2_THREADS; i++) + { + args[i] = i; + threads[i] = NdbThread_Create(test2func, // Function + (void**)&args[i],// Arg + 2048, // Stacksize + (char*)"test2thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + if (threads[i] == NULL) + fail("TEST2", "NdbThread_Create failed"); + } + + ndbout << "All threads created" << endl; + + NdbMutex_Unlock(test2mutex); + + for (int i = 0; i < T2_THREADS; i++) + { + if (NdbThread_WaitFor(threads[i], &status2)) + fail("TEST2", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&threads[i]); + // Don't test return values + // ndbout << "thread" << i << " returned, status = " << status2 << endl; + // if (status2 != i) + // fail("TEST2", "Wrong status"); + } + + if (NdbMutex_Lock(test2mutex) != 0) + fail("TEST2", "NdbMutex_Lock failed"); + if (NdbMutex_Unlock(test2mutex) != 0) + fail("TEST2", "NdbMutex_Unlock failed"); + if (NdbMutex_Destroy(test2mutex) != 0) + fail("TEST2", "NdbMutex_Destroy failed"); + ndbout << "TEST2 completed" << endl; + + ndbout << "= TEST3 ===============================" << endl; + // Create 10 threads that will by synchronised by a condition + // When they are awakened and have the mutex they will increment a global variable +#define T3_THREADS 10 + NdbThread* t3threads[T3_THREADS]; + int t3args[T3_THREADS]; + void *status3 = 0; + + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + testthreadsdone = 0; + + for (int i = 0; i < T3_THREADS; i++) + { + t3args[i] = i; + t3threads[i] = NdbThread_Create(testfunc, // Function + (void**)&t3args[i],// Arg + 2048, // Stacksize + (char*)"test3thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + } + + ndbout << "All threads created" << endl; + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST3", "NdbMutex_Lock failed"); + + while (testthreadsdone < T3_THREADS*10) + { + if(NdbCondition_Wait(testcond, testmutex) != 0) + fail("TEST3", "NdbCondition_Wait failed"); + ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl; + } + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST3", "NdbMutex_Unlock failed"); + + for (int i = 0; i < T3_THREADS; i++) + { + if (NdbThread_WaitFor(t3threads[i], &status3) != 0) + fail("TEST3", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&t3threads[i]); + //ndbout << "thread" << i << " returned, status = " << status3 << endl; + //if (status3 != i) + // fail("TEST3", "Wrong status"); + } + + NdbMutex_Destroy(testmutex); + NdbCondition_Destroy(testcond); + ndbout << "TEST3 completed" << endl; + + ndbout << "= TEST4 ===============================" << endl; + // Check tick functions + + //#if 0 + + int sleeptimes[] = {78, 12, 199, 567, 899}; + + + for (int i = 0; i < 5; i++) + { + ndbout << "*------------------------------- Measure" << i << endl; + + NDB_TICKS millisec_now; + NDB_TICKS millisec_now2; + + millisec_now = NdbTick_CurrentMillisecond(); + NdbSleep_MilliSleep(sleeptimes[i]); + millisec_now2 = NdbTick_CurrentMillisecond(); + + ndbout << " Time before sleep = " << millisec_now << endl; + ndbout << " Time after sleep = " << millisec_now2 << endl; + ndbout << " Tried to sleep "<<sleeptimes[i]<<" milliseconds." << endl; + ndbout << " Sleep time was " << millisec_now2 -millisec_now <<" milliseconds." << endl; + + } + + ndbout << "TEST4 completed" << endl; + + ndbout << "= TEST5 ===============================" << endl; + // Check NdbOut + + ndbout << "Testing hex and dec functions of NdbOut" << endl; + + for (int i = 0; i<= 0xFF; i++) + { + ndbout << i << "=" <<hex << i << "="<<dec << i << ", "; + } + + ndbout << endl<< "Testing that hex is reset to dec by endl" << endl; + ndbout << hex << 67 << endl; + ndbout << 67 << endl; + + ndbout << "TEST5 completed" << endl; + + + ndbout << "= TEST6 ===============================" << endl; + const char* theEnvHostNamePtr; + char buf[255]; + char theHostHostName[256]; + theEnvHostNamePtr = NdbEnv_GetEnv("HOSTNAME", buf, 255); + if(theEnvHostNamePtr == NULL) + fail("TEST6", "Could not get HOSTNAME from env"); + else{ + ndbout << "HOSTNAME from GetEnv" << theEnvHostNamePtr << endl; + + NdbHost_GetHostName(theHostHostName); + + ndbout << "HOSTNAME from GetHostName" <<theHostHostName << endl; + + if (strcmp(theEnvHostNamePtr, theHostHostName) != 0) + fail("TEST6", "NdbHost_GetHostName or NdbEnv_GetEnv failed"); + } + + ndbout << "= TEST7 ===============================" << endl; + + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + testthreadsdone = 0; + + for (int i = 0; i < T3_THREADS; i++) + { + t3args[i] = i; + t3threads[i] = NdbThread_Create(testfunc, // Function + (void**)&t3args[i],// Arg + 2048, // Stacksize + (char*)"test7thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + } + + ndbout << "All threads created" << endl; + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST7", "NdbMutex_Lock failed"); + + while (testthreadsdone < T3_THREADS*10) + { + // just testing the functionality without timing out, therefor 20 sec. + if(NdbCondition_WaitTimeout(testcond, testmutex, 20000) != 0) + fail("TEST7", "NdbCondition_WaitTimeout failed"); + ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl; + } + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST7", "NdbMutex_Unlock failed"); + + for (int i = 0; i < T3_THREADS; i++) + { + if (NdbThread_WaitFor(t3threads[i], &status3) != 0) + fail("TEST7", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&t3threads[i]); + } + + NdbMutex_Destroy(testmutex); + NdbCondition_Destroy(testcond); + + ndbout << "TEST7 completed" << endl; + + + ndbout << "= TEST8 ===============================" << endl; + ndbout << " NdbCondition_WaitTimeout" << endl; + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + + for (int i = 0; i < 5; i++) + { + ndbout << "*------------------------------- Measure" << i << endl; + + NDB_TICKS millisec_now; + NDB_TICKS millisec_now2; + + millisec_now = NdbTick_CurrentMillisecond(); + if (NdbCondition_WaitTimeout(testcond, testmutex, sleeptimes[i]) != 0) + fail("TEST8", "NdbCondition_WaitTimeout failed"); + millisec_now2 = NdbTick_CurrentMillisecond(); + + ndbout << " Time before WaitTimeout = " << millisec_now << endl; + ndbout << " Time after WaitTimeout = " << millisec_now2 << endl; + ndbout << " Tried to wait "<<sleeptimes[i]<<" milliseconds." << endl; + ndbout << " Wait time was " << millisec_now2 -millisec_now <<" milliseconds." << endl; + + } + + ndbout << "TEST8 completed" << endl; + + + ndbout << "= TEST9 ===============================" << endl; + ndbout << " NdbTick_CurrentXXXXXsecond compare" << endl; + + for (int i = 0; i < 5; i++) + { + ndbout << "*------------------------------- Measure" << i << endl; + + NDB_TICKS millisec_now; + NDB_TICKS millisec_now2; + Uint32 usec_now, usec_now2; + Uint64 msec_now, msec_now2; + + + millisec_now = NdbTick_CurrentMillisecond(); + NdbTick_CurrentMicrosecond( &msec_now, &usec_now); + + NdbSleep_MilliSleep(sleeptimes[i]); + + millisec_now2 = NdbTick_CurrentMillisecond(); + NdbTick_CurrentMicrosecond( &msec_now2, &usec_now2); + + Uint64 usecdiff = time_diff(msec_now,msec_now2,usec_now,usec_now2); + NDB_TICKS msecdiff = millisec_now2 -millisec_now; + + ndbout << " Slept "<<sleeptimes[i]<<" milliseconds." << endl; + ndbout << " Measured " << msecdiff <<" milliseconds with milli function ." << endl; + ndbout << " Measured " << usecdiff/1000 << "," << usecdiff%1000<<" milliseconds with micro function ." << endl; + } + + ndbout << "TEST9 completed" << endl; + + + const int iter = 20; + ndbout << "Testing microsecond timer - " << iter << " iterations" << endl; + testMicros(iter); + ndbout << "Testing microsecond timer - COMPLETED" << endl; + +#if defined NDB_OSE || defined NDB_SOFTOSE + ndbout << "system_tick() = " << system_tick() << " us per tick" << endl; +#endif + + + ndbout << "= TEST10 ===============================" << endl; + + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + testthreadsdone = 0; + + for (int i = 0; i < T3_THREADS; i++) + { + t3args[i] = i; + t3threads[i] = NdbThread_Create(testTryLockfunc, // Function + (void**)&t3args[i],// Arg + 2048, // Stacksize + (char*)"test10thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + } + + ndbout << "All threads created" << endl; + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST10", "NdbMutex_Lock failed"); + + while (testthreadsdone < T3_THREADS*10) + { + if(NdbCondition_Wait(testcond, testmutex) != 0) + fail("TEST10", "NdbCondition_WaitTimeout failed"); + ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl; + } + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST10", "NdbMutex_Unlock failed"); + + for (int i = 0; i < T3_THREADS; i++) + { + if (NdbThread_WaitFor(t3threads[i], &status3) != 0) + fail("TEST10", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&t3threads[i]); + } + + NdbMutex_Destroy(testmutex); + NdbCondition_Destroy(testcond); + + ndbout << "TEST10 completed" << endl; + + + // Check total status of test + + if (TestHasFailed == 1) + ndbout << endl << "TEST FAILED!" << endl; + else + ndbout << endl << "TEST PASSED!" << endl; + + return TestHasFailed; + +}; + +Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2){ + + Uint64 diff = 0; + diff += (s2 - s1) * 1000000; + if(m2 >= m1) + diff += (m2 - m1); + else { + diff += m2; + diff -= m1; + } + + // if(0) + // ndbout("(s1,m1) = (%d, %d) (s2,m2) = (%d, %d) -> diff = %d\n", + // (Uint32)s1,m1,(Uint32)s2,m2, (Uint32)diff); + + return diff; +}; + +void +testMicros(int count){ + Uint32 avg = 0; + Uint32 sum2 = 0; + + for(int i = 0; i<count; i++){ + Uint64 s1, s2; + Uint32 m1, m2; + if(NdbTick_CurrentMicrosecond(&s1, &m1) != 0){ + ndbout << "Failed to get current micro" << endl; + TestHasFailed = 1; + return; + } + Uint32 r = (rand() % 1000) + 1; + NdbSleep_MilliSleep(r); + if(NdbTick_CurrentMicrosecond(&s2, &m2) != 0){ + ndbout << "Failed to get current micro" << endl; + TestHasFailed = 1; + return; + } + Uint64 m = time_diff(s1,s2,m1,m2); + if(verbose) + ndbout << "Slept for " << r << " ms" + << " - Measured " << m << " us" << endl; + + if(m > (r*1000)){ + avg += (m - (r*1000)); + sum2 += (m - (r*1000)) * (m - (r*1000)); + } else { + avg += ((r*1000) - m); + sum2 += ((r*1000) - m) * ((r*1000) - m); + } +#if 0 + m /= 1000; + if(m > r && ((m - r) > 10)){ + ndbout << "Difference to big: " << (m - r) << " - Test failed" << endl; + TestHasFailed = 1; + } + if(m < r && ((r - m) > 10)){ + ndbout << "Difference to big: " << (r - m) << " - Test failed" << endl; + TestHasFailed = 1; + } +#endif + } + + Uint32 dev = (avg * avg - sum2) / count; dev /= count; + avg /= count; + + Uint32 t = 0; + while((t*t)<dev) t++; + ndbout << "NOTE - measure are compared to NdbSleep_MilliSleep(...)" << endl; + ndbout << "Average error = " << avg << " us" << endl; + ndbout << "Stddev error = " << t << " us" << endl; +} diff --git a/ndb/src/common/portlib/unix/Makefile b/ndb/src/common/portlib/unix/Makefile new file mode 100644 index 00000000000..452196d9f08 --- /dev/null +++ b/ndb/src/common/portlib/unix/Makefile @@ -0,0 +1,27 @@ +include .defs.mk + +TYPE := util + +PIC_ARCHIVE := Y +ARCHIVE_TARGET := portlib + +SOURCES.c = NdbCondition.c \ + NdbMutex.c \ + NdbSleep.c \ + NdbTick.c \ + NdbEnv.c \ + NdbThread.c \ + NdbHost.c \ + NdbTCP.c \ + NdbDaemon.c + +ifeq ($(NDB_OS), SOFTOSE) + SOURCES += NdbMem_SoftOse.cpp +else + SOURCES.c += NdbMem.c +endif + +include $(NDB_TOP)/Epilogue.mk + +testNdbDaemon: NdbDaemon.c + $(CC) -o $@ NdbDaemon.c $(CCFLAGS) -DNDB_DAEMON_TEST -L$(NDB_TOP)/lib diff --git a/ndb/src/common/portlib/unix/NdbCondition.c b/ndb/src/common/portlib/unix/NdbCondition.c new file mode 100644 index 00000000000..35b80821052 --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbCondition.c @@ -0,0 +1,179 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <NdbCondition.h> +#include <pthread.h> +#include <assert.h> +#include <sys/types.h> +#if defined NDB_MACOSX +#include <stdlib.h> +#else +#include <malloc.h> +#endif + +#include <NdbMutex.h> + +struct NdbCondition +{ + pthread_cond_t cond; +}; + + + +struct NdbCondition* +NdbCondition_Create(void) +{ + struct NdbCondition* tmpCond; + int result; + + tmpCond = (struct NdbCondition*)malloc(sizeof(struct NdbCondition)); + + if (tmpCond == NULL) + return NULL; + + result = pthread_cond_init(&tmpCond->cond, NULL); + + assert(result==0); + return tmpCond; +} + + + +int +NdbCondition_Wait(struct NdbCondition* p_cond, + NdbMutex* p_mutex) +{ + int result; + + if (p_cond == NULL || p_mutex == NULL) + return 1; + + result = pthread_cond_wait(&p_cond->cond, p_mutex); + + return result; +} + +#if defined NDB_SOLARIS || defined NDB_HPUX +#include <time.h> +int +NdbCondition_WaitTimeout(struct NdbCondition* p_cond, + NdbMutex* p_mutex, + int msecs){ + int result; + struct timespec abstime; + int secs = 0; + + if (p_cond == NULL || p_mutex == NULL) + return 1; + + clock_gettime(CLOCK_REALTIME, &abstime); + + if(msecs >= 1000){ + secs = msecs / 1000; + msecs = msecs % 1000; + } + + abstime.tv_sec += secs; + abstime.tv_nsec += msecs * 1000000; + if (abstime.tv_nsec >= 1000000000) { + abstime.tv_sec += 1; + abstime.tv_nsec -= 1000000000; + } + + result = pthread_cond_timedwait(&p_cond->cond, p_mutex, &abstime); + + return result; +} +#endif + +#if defined NDB_LINUX || defined NDB_MACOSX +#include <unistd.h> +#include <sys/time.h> + +int +NdbCondition_WaitTimeout(struct NdbCondition* p_cond, + NdbMutex* p_mutex, + int msecs){ + int result; + struct timespec abstime; + struct timeval tick_time; + int secs = 0; + + if (p_cond == NULL || p_mutex == NULL) + return 1; + + gettimeofday(&tick_time, 0); + + if(msecs >= 1000){ + secs = msecs / 1000; + msecs = msecs % 1000; + } + + + abstime.tv_sec = tick_time.tv_sec + secs; + abstime.tv_nsec = tick_time.tv_usec * 1000 + msecs * 1000000; + if (abstime.tv_nsec >= 1000000000) { + abstime.tv_sec += 1; + abstime.tv_nsec -= 1000000000; + } + + result = pthread_cond_timedwait(&p_cond->cond, p_mutex, &abstime); + + return result; +} +#endif + + +int +NdbCondition_Signal(struct NdbCondition* p_cond){ + int result; + + if (p_cond == NULL) + return 1; + + result = pthread_cond_signal(&p_cond->cond); + + return result; +} + + +int NdbCondition_Broadcast(struct NdbCondition* p_cond) +{ + int result; + + if (p_cond == NULL) + return 1; + + result = pthread_cond_broadcast(&p_cond->cond); + + return result; +} + + +int NdbCondition_Destroy(struct NdbCondition* p_cond) +{ + int result; + + if (p_cond == NULL) + return 1; + + result = pthread_cond_destroy(&p_cond->cond); + free(p_cond); + + return 0; +} + diff --git a/ndb/src/common/portlib/unix/NdbDaemon.c b/ndb/src/common/portlib/unix/NdbDaemon.c new file mode 100644 index 00000000000..fc114266c9d --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbDaemon.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "NdbDaemon.h" +#include <assert.h> + +#ifdef NDB_LINUX +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#endif + +#ifdef NDB_SOLARIS +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#endif + +#define NdbDaemon_ErrorSize 500 +#if defined(NDB_LINUX) || defined(NDB_SOLARIS) +long NdbDaemon_DaemonPid; +int NdbDaemon_ErrorCode; +char NdbDaemon_ErrorText[NdbDaemon_ErrorSize]; +#endif +int +NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags) +{ + /* XXX fix other unixes */ +#if defined(NDB_LINUX) || defined(NDB_SOLARIS) + int lockfd = -1, logfd = -1, n; + char buf[64]; + + /* Check that we have write access to lock file */ + assert(lockfile != NULL); + lockfd = open(lockfile, O_CREAT|O_RDWR, 0644); + if (lockfd == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: open for write failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Read any old pid from lock file */ + buf[0] = 0; + n = read(lockfd, buf, sizeof(buf)); + if (n < 0) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: read failed: %s", lockfile, strerror(errno)); + return -1; + } + NdbDaemon_DaemonPid = atol(buf); + if (lseek(lockfd, 0, SEEK_SET) == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: lseek failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Test for lock before becoming daemon */ + if (lockf(lockfd, F_TEST, 0) == -1) { + if (errno == EACCES || errno == EAGAIN) { /* results may vary */ + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid); + return -1; + } + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: lock test failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Test open log file before becoming daemon */ + if (logfile != NULL) { + logfd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0644); + if (logfd == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: open for write failed: %s", logfile, strerror(errno)); + return -1; + } + } + /* Fork */ + n = fork(); + if (n == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "fork failed: %s", strerror(errno)); + return -1; + } + /* Exit if we are the parent */ + if (n != 0) { + exit(0); + } + /* Running in child process */ + NdbDaemon_DaemonPid = getpid(); + /* Lock the lock file (likely to succeed due to test above) */ + if (lockf(lockfd, F_LOCK, 0) == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: lock failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Become process group leader */ + if (setsid() == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "setsid failed: %s", strerror(errno)); + return -1; + } + /* Write pid to lock file */ + if (ftruncate(lockfd, 0) == -1) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: ftruncate failed: %s", lockfile, strerror(errno)); + return -1; + } + sprintf(buf, "%ld\n", NdbDaemon_DaemonPid); + n = strlen(buf); + if (write(lockfd, buf, n) != n) { + NdbDaemon_ErrorCode = errno; + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: write failed: %s", lockfile, strerror(errno)); + return -1; + } + /* Do input/output redirections (assume fd 0,1,2 not in use) */ + close(0); + open("/dev/null", O_RDONLY); + if (logfile != 0) { + dup2(logfd, 1); + dup2(logfd, 2); + close(logfd); + } +#endif + /* Success */ + return 0; +} + +#ifdef NDB_DAEMON_TEST + +int +main() +{ + if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) { + fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText); + return 1; + } + sleep(10); + return 0; +} + +#endif diff --git a/ndb/src/common/portlib/unix/NdbEnv.c b/ndb/src/common/portlib/unix/NdbEnv.c new file mode 100644 index 00000000000..b01e3b239ca --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbEnv.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbEnv.h" +#include <string.h> +#include <stdlib.h> + +const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen) +{ + char* p = NULL; + p = getenv(name); + + if (p != NULL && buf != NULL){ + strncpy(buf, p, buflen); + buf[buflen-1] = 0; + } + return p; + +} + diff --git a/ndb/src/common/portlib/unix/NdbHost.c b/ndb/src/common/portlib/unix/NdbHost.c new file mode 100644 index 00000000000..8d2a23fccda --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbHost.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbHost.h" +#include <unistd.h> + +int NdbHost_GetHostName(char* buf) +{ + if (gethostname(buf, MAXHOSTNAMELEN) != 0) + { + return -1; + } + return 0; +} + +int NdbHost_GetProcessId(void) +{ + return getpid(); +} + diff --git a/ndb/src/common/portlib/unix/NdbMem.c b/ndb/src/common/portlib/unix/NdbMem.c new file mode 100644 index 00000000000..a18cf30cc8a --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbMem.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbMem.h" + +#include <assert.h> +#include <assert.h> +#include <stdlib.h> +#ifndef NDB_MACOSX +#include <sys/mman.h> +#endif + +void NdbMem_Create() +{ + /* Do nothing */ + return; +} + +void NdbMem_Destroy() +{ + /* Do nothing */ + return; +} + +void* NdbMem_Allocate(size_t size) +{ + assert(size > 0); + return (void*)malloc(size); +} + +void* NdbMem_AllocateAlign(size_t size, size_t alignment) +{ + /* + return (void*)memalign(alignment, size); + TEMP fix + */ + return (void*)malloc(size); +} + + +void NdbMem_Free(void* ptr) +{ + free(ptr); +} + + +int NdbMem_MemLockAll(){ +#if defined NDB_MACOSX + return 0; +#else + return mlockall(MCL_CURRENT | MCL_FUTURE); +#endif +} + +int NdbMem_MemUnlockAll(){ +#if defined NDB_MACOSX + return 0; +#else + return munlockall(); +#endif +} + diff --git a/ndb/src/common/portlib/unix/NdbMutex.c b/ndb/src/common/portlib/unix/NdbMutex.c new file mode 100644 index 00000000000..3cadc0667e7 --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbMutex.c @@ -0,0 +1,93 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbMutex.h" + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> + +NdbMutex* NdbMutex_Create(void) +{ + NdbMutex* pNdbMutex; + int result; + + pNdbMutex = (NdbMutex*)malloc(sizeof(NdbMutex)); + + if (pNdbMutex == NULL) + return NULL; + + result = pthread_mutex_init(pNdbMutex, NULL); + assert(result == 0); + + return pNdbMutex; + +} + + +int NdbMutex_Destroy(NdbMutex* p_mutex) +{ + int result; + + if (p_mutex == NULL) + return -1; + + result = pthread_mutex_destroy(p_mutex); + free(p_mutex); + + return result; + +} + + +int NdbMutex_Lock(NdbMutex* p_mutex) +{ + int result; + + if (p_mutex == NULL) + return -1; + + result = pthread_mutex_lock(p_mutex); + + return result; +} + + +int NdbMutex_Unlock(NdbMutex* p_mutex) +{ + int result; + + if (p_mutex == NULL) + return -1; + + result = pthread_mutex_unlock(p_mutex); + + return result; +} + + +int NdbMutex_Trylock(NdbMutex* p_mutex) +{ + int result = -1; + + if (p_mutex != NULL) { + result = pthread_mutex_trylock(p_mutex); + } + + return result; +} + diff --git a/ndb/src/common/portlib/unix/NdbSleep.c b/ndb/src/common/portlib/unix/NdbSleep.c new file mode 100644 index 00000000000..35132d7f9c7 --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbSleep.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbSleep.h" + + +#ifdef NDB_SOLARIS +#include <sys/types.h> +#include <unistd.h> +#endif + +#if defined NDB_LINUX || defined NDB_HPUX || defined NDB_MACOSX +#include <time.h> +#include <unistd.h> +#endif + +int +NdbSleep_MilliSleep(int milliseconds){ + int result = 0; + struct timespec sleeptime; + sleeptime.tv_sec = milliseconds / 1000; + sleeptime.tv_nsec = (milliseconds - (sleeptime.tv_sec * 1000)) * 1000000; + result = nanosleep(&sleeptime, NULL); + return result; +} + +int +NdbSleep_SecSleep(int seconds){ + int result = 0; + result = sleep(seconds); + return result; +} + + diff --git a/ndb/src/common/portlib/unix/NdbTCP.c b/ndb/src/common/portlib/unix/NdbTCP.c new file mode 100644 index 00000000000..c2613c211c5 --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbTCP.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbTCP.h" + + +#ifdef NDB_SOLARIS +int +Ndb_getInAddr(struct in_addr * dst, const char *address) { + struct hostent host, * hostPtr; + char buf[1024]; + int h_errno; + hostPtr = gethostbyname_r(address, &host, &buf[0], 1024, &h_errno); + if (hostPtr != NULL) { + dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr; + return 0; + } + + /* Try it as aaa.bbb.ccc.ddd. */ + dst->s_addr = inet_addr(address); + if (dst->s_addr != -1) { + return 0; + } + return -1; +} +#endif + +#if defined NDB_LINUX || defined NDB_HPUX || defined NDB_MACOSX +int +Ndb_getInAddr(struct in_addr * dst, const char *address) { + struct hostent * hostPtr; + hostPtr = gethostbyname(address); + if (hostPtr != NULL) { + dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr; + return 0; + } + + /* Try it as aaa.bbb.ccc.ddd. */ + dst->s_addr = inet_addr(address); + if (dst->s_addr != -1) { + return 0; + } + return -1; +} +#endif + diff --git a/ndb/src/common/portlib/unix/NdbThread.c b/ndb/src/common/portlib/unix/NdbThread.c new file mode 100644 index 00000000000..3665c4c9159 --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbThread.c @@ -0,0 +1,119 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbThread.h" +#include <pthread.h> +#ifdef NDB_MACOSX +#include <stdlib.h> +#else +#include <malloc.h> +#endif +#include <assert.h> +#include <string.h> +#include <NdbStdio.h> + +#define MAX_THREAD_NAME 16 + + +struct NdbThread +{ + pthread_t thread; + char thread_name[MAX_THREAD_NAME]; +}; + + + +struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, + NDB_THREAD_ARG *p_thread_arg, + const NDB_THREAD_STACKSIZE thread_stack_size, + const char* p_thread_name, + NDB_THREAD_PRIO thread_prio) +{ + struct NdbThread* tmpThread; + int result; + pthread_attr_t thread_attr; + + if (p_thread_func == NULL) + return 0; + + tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread)); + if (tmpThread == NULL) + return NULL; + + snprintf(tmpThread->thread_name, sizeof(tmpThread->thread_name), + "%s", p_thread_name); + + pthread_attr_init(&thread_attr); + pthread_attr_setstacksize(&thread_attr, thread_stack_size); +#if defined NDB_SOLARIS +#if !defined NDB_SOLARIS6 + /* Guard stack overflow with a 2k databuffer */ + pthread_attr_setguardsize(&thread_attr, 2048); +#endif +#endif + + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); + result = pthread_create(&tmpThread->thread, + &thread_attr, + p_thread_func, + p_thread_arg); + assert(result==0); + + pthread_attr_destroy(&thread_attr); + return tmpThread; +} + + +void NdbThread_Destroy(struct NdbThread** p_thread) +{ + if (*p_thread != NULL){ + free(* p_thread); + * p_thread = 0; + } +} + + +int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status) +{ + int result; + + if (p_wait_thread == NULL) + return 0; + + if (p_wait_thread->thread == NULL) + return 0; + + result = pthread_join(p_wait_thread->thread, status); + + return result; +} + + +void NdbThread_Exit(int status) +{ + pthread_exit(&status); +} + + +int NdbThread_SetConcurrencyLevel(int level) +{ +#ifndef NDB_SOLARIS6 + return pthread_setconcurrency(level); +#else + return 0; +#endif +} diff --git a/ndb/src/common/portlib/unix/NdbTick.c b/ndb/src/common/portlib/unix/NdbTick.c new file mode 100644 index 00000000000..5adb4ec80c2 --- /dev/null +++ b/ndb/src/common/portlib/unix/NdbTick.c @@ -0,0 +1,110 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbTick.h" +#include <time.h> + +#define NANOSEC_PER_SEC 1000000000 +#define MICROSEC_PER_SEC 1000000 +#define MILLISEC_PER_SEC 1000 +#define MICROSEC_PER_MILLISEC 1000 +#define MILLISEC_PER_NANOSEC 1000000 + + +#if defined NDB_SOLARIS || NDB_HPUX +NDB_TICKS NdbTick_CurrentMillisecond(void) +{ + struct timespec tick_time; + clock_gettime(CLOCK_REALTIME, &tick_time); + + return + ((NDB_TICKS)tick_time.tv_sec) * ((NDB_TICKS)MILLISEC_PER_SEC) + + ((NDB_TICKS)tick_time.tv_nsec) / ((NDB_TICKS)MILLISEC_PER_NANOSEC); +} + +int +NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){ + struct timespec t; + int res = clock_gettime(CLOCK_REALTIME, &t); + * secs = t.tv_sec; + * micros = t.tv_nsec / 1000; + return res; +} +#endif + +#if defined NDB_LINUX || NDB_MACOSX +#include <unistd.h> +#include <sys/time.h> +NDB_TICKS NdbTick_CurrentMillisecond(void) +{ + struct timeval tick_time; + gettimeofday(&tick_time, 0); + + return + ((NDB_TICKS)tick_time.tv_sec) * ((NDB_TICKS)MILLISEC_PER_SEC) + + ((NDB_TICKS)tick_time.tv_usec) / ((NDB_TICKS)MICROSEC_PER_MILLISEC); +} + +int +NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){ + struct timeval tick_time; + int res = gettimeofday(&tick_time, 0); + + if(secs==0) { + NDB_TICKS secs = tick_time.tv_sec; + *micros = tick_time.tv_usec; + *micros = secs*1000000+*micros; + } else { + * secs = tick_time.tv_sec; + * micros = tick_time.tv_usec; + } + return res; +} + +#endif +#ifdef TIME_MEASUREMENT +int +NdbTick_getMicroTimer(struct MicroSecondTimer* input_timer) +{ + NDB_TICKS secs; + Uint32 mics; + int ret_value; + ret_value = NdbTick_CurrentMicrosecond(&secs, &mics); + input_timer->seconds = secs; + input_timer->micro_seconds = (NDB_TICKS)mics; + return ret_value; +} + +NDB_TICKS +NdbTick_getMicrosPassed(struct MicroSecondTimer start, + struct MicroSecondTimer stop) +{ + NDB_TICKS ret_value = (NDB_TICKS)0; + if (start.seconds < stop.seconds) { + NDB_TICKS sec_passed = stop.seconds - start.seconds; + ret_value = ((NDB_TICKS)MICROSEC_PER_SEC) * sec_passed; + } else if (start.seconds > stop.seconds) { + return ret_value; + }//if + if (start.micro_seconds < stop.micro_seconds) { + ret_value += (stop.micro_seconds - start.micro_seconds); + } else if (ret_value != (NDB_TICKS)0) { + ret_value -= (start.micro_seconds - stop.micro_seconds); + }//if + return ret_value; +} +#endif diff --git a/ndb/src/common/portlib/win32/Makefile b/ndb/src/common/portlib/win32/Makefile new file mode 100644 index 00000000000..bb29ac5547e --- /dev/null +++ b/ndb/src/common/portlib/win32/Makefile @@ -0,0 +1,30 @@ +include .defs.mk + +TYPE := util + +PIC_ARCHIVE := Y +ARCHIVE_TARGET := portlib + +SOURCES.c = NdbCondition.c \ + NdbMutex.c \ + NdbSleep.c \ + NdbTick.c \ + NdbEnv.c \ + NdbThread.c \ + NdbHost.c \ + NdbTCP.c \ + NdbDaemon.c + +ifeq ($(NDB_OS), SOFTOSE) + SOURCES += NdbMem_SoftOse.cpp +else + SOURCES.c += NdbMem.c +endif + +include $(NDB_TOP)/Epilogue.mk + + + + + + diff --git a/ndb/src/common/portlib/win32/NdbCondition.c b/ndb/src/common/portlib/win32/NdbCondition.c new file mode 100644 index 00000000000..12b508cf33b --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbCondition.c @@ -0,0 +1,184 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <winsock2.h> +#include <ws2tcpip.h> +#include <windows.h> +#include <assert.h> +#include <sys/types.h> + +#include "NdbCondition.h" +#include <NdbMutex.h> + + +struct NdbCondition +{ + long nWaiters; + NdbMutex* pNdbMutexWaitersLock; + HANDLE hSemaphore; + HANDLE hEventWaitersDone; + int bWasBroadcast; +}; + + +struct NdbCondition* +NdbCondition_Create(void) +{ + int result = 0; + struct NdbCondition* pNdbCondition = (struct NdbCondition*)malloc(sizeof(struct NdbCondition)); + if(!pNdbCondition) + return 0; + + pNdbCondition->nWaiters = 0; + pNdbCondition->bWasBroadcast = 0; + if(!(pNdbCondition->hSemaphore = CreateSemaphore(0, 0, MAXLONG, 0))) + result = -1; + else if(!(pNdbCondition->pNdbMutexWaitersLock = NdbMutex_Create())) + result = -1; + else if(!(pNdbCondition->hEventWaitersDone = CreateEvent(0, 0, 0, 0))) + result = -1; + + assert(!result); + return pNdbCondition; +} + + +int +NdbCondition_Wait(struct NdbCondition* p_cond, + NdbMutex* p_mutex) +{ + int result; + int bLastWaiter; + if(!p_cond || !p_mutex) + return 1; + + NdbMutex_Lock(p_cond->pNdbMutexWaitersLock); + p_cond->nWaiters++; + NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock); + + if(NdbMutex_Unlock(p_mutex)) + return -1; + result = WaitForSingleObject (p_cond->hSemaphore, INFINITE); + + NdbMutex_Lock(p_cond->pNdbMutexWaitersLock); + p_cond->nWaiters--; + bLastWaiter = (p_cond->bWasBroadcast && p_cond->nWaiters==0); + NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock); + + if(result==WAIT_OBJECT_0 && bLastWaiter) + SetEvent(p_cond->hEventWaitersDone); + + NdbMutex_Lock(p_mutex); + return result; +} + + +int +NdbCondition_WaitTimeout(struct NdbCondition* p_cond, + NdbMutex* p_mutex, + int msecs) +{ + int result; + int bLastWaiter; + if (!p_cond || !p_mutex) + return 1; + + NdbMutex_Lock(p_cond->pNdbMutexWaitersLock); + p_cond->nWaiters++; + NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock); + if(msecs<0) + msecs = 0; + + if(NdbMutex_Unlock(p_mutex)) + return -1; + result = WaitForSingleObject(p_cond->hSemaphore, msecs); + + NdbMutex_Lock(p_cond->pNdbMutexWaitersLock); + p_cond->nWaiters--; + bLastWaiter = (p_cond->bWasBroadcast && p_cond->nWaiters==0); + NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock); + + if(result!=WAIT_OBJECT_0) + result = -1; + + if(bLastWaiter) + SetEvent(p_cond->hEventWaitersDone); + + NdbMutex_Lock(p_mutex); + return result; +} + + +int +NdbCondition_Signal(struct NdbCondition* p_cond) +{ + int bHaveWaiters; + if(!p_cond) + return 1; + + NdbMutex_Lock(p_cond->pNdbMutexWaitersLock); + bHaveWaiters = (p_cond->nWaiters > 0); + NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock); + + if(bHaveWaiters) + return (ReleaseSemaphore(p_cond->hSemaphore, 1, 0) ? 0 : -1); + else + return 0; +} + + +int NdbCondition_Broadcast(struct NdbCondition* p_cond) +{ + int bHaveWaiters; + int result = 0; + if(!p_cond) + return 1; + + NdbMutex_Lock(p_cond->pNdbMutexWaitersLock); + bHaveWaiters = 0; + if(p_cond->nWaiters > 0) + { + p_cond->bWasBroadcast = !0; + bHaveWaiters = 1; + } + NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock); + if(bHaveWaiters) + { + if(!ReleaseSemaphore(p_cond->hSemaphore, p_cond->nWaiters, 0)) + result = -1; + else if(WaitForSingleObject (p_cond->hEventWaitersDone, INFINITE) != WAIT_OBJECT_0) + result = -1; + p_cond->bWasBroadcast = 0; + } + return result; +} + + +int NdbCondition_Destroy(struct NdbCondition* p_cond) +{ + int result; + if(!p_cond) + return 1; + + CloseHandle(p_cond->hEventWaitersDone); + NdbMutex_Destroy(p_cond->pNdbMutexWaitersLock); + result = (CloseHandle(p_cond->hSemaphore) ? 0 : -1); + + free(p_cond); + return 0; +} + diff --git a/ndb/src/common/portlib/win32/NdbDaemon.c b/ndb/src/common/portlib/win32/NdbDaemon.c new file mode 100644 index 00000000000..b96d4c20260 --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbDaemon.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "NdbDaemon.h" + +#define NdbDaemon_ErrorSize 500 +long NdbDaemon_DaemonPid; +int NdbDaemon_ErrorCode; +char NdbDaemon_ErrorText[NdbDaemon_ErrorSize]; + +int +NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags) +{ + // XXX do something + return 0; +} + +#ifdef NDB_DAEMON_TEST + +int +main() +{ + if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) { + fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText); + return 1; + } + sleep(10); + return 0; +} + +#endif diff --git a/ndb/src/common/portlib/win32/NdbEnv.c b/ndb/src/common/portlib/win32/NdbEnv.c new file mode 100644 index 00000000000..0df703a5e97 --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbEnv.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbEnv.h" +#include <string.h> +#include <stdlib.h> + +const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen) +{ + char* p = NULL; + p = getenv(name); + + if (p != NULL && buf != NULL){ + strncpy(buf, p, buflen); + buf[buflen-1] = 0; + } + return p; +} + diff --git a/ndb/src/common/portlib/win32/NdbHost.c b/ndb/src/common/portlib/win32/NdbHost.c new file mode 100644 index 00000000000..f91dd1a531c --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbHost.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbHost.h" +#include <windows.h> +#include <process.h> + + +int NdbHost_GetHostName(char* buf) +{ + /* We must initialize TCP/IP if we want to call gethostname */ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 2, 0 ); + err = WSAStartup( wVersionRequested, &wsaData ); + if ( err != 0 ) { + /** + * Tell the user that we couldn't find a usable + * WinSock DLL. + */ + return -1; + } + + /* Get host name */ + if(gethostname(buf, MAXHOSTNAMELEN)) + { + return -1; + } + return 0; +} + + +int NdbHost_GetProcessId(void) +{ + return _getpid(); +} + diff --git a/ndb/src/common/portlib/win32/NdbMem.c b/ndb/src/common/portlib/win32/NdbMem.c new file mode 100644 index 00000000000..274dc31353f --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbMem.c @@ -0,0 +1,237 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <windows.h> +#include <assert.h> +#include <NdbStdio.h> + +#include "NdbMem.h" + + +struct AWEINFO +{ + SIZE_T dwSizeInBytesRequested; + ULONG_PTR nNumberOfPagesRequested; + ULONG_PTR nNumberOfPagesActual; + ULONG_PTR nNumberOfPagesFreed; + ULONG_PTR* pnPhysicalMemoryPageArray; + void* pRegionReserved; +}; + +const size_t cNdbMem_nMaxAWEinfo = 256; +size_t gNdbMem_nAWEinfo = 0; + +struct AWEINFO* gNdbMem_pAWEinfo = 0; + + +void ShowLastError(const char* szContext, const char* szFunction) +{ + DWORD dwError = GetLastError(); + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, + 0, + NULL + ); + printf("%s : %s failed : %lu : %s\n", szContext, szFunction, dwError, (char*)lpMsgBuf); + LocalFree(lpMsgBuf); +} + + + +void NdbMem_Create() +{ + // Address Windowing Extensions + struct PRIVINFO + { + DWORD Count; + LUID_AND_ATTRIBUTES Privilege[1]; + } Info; + + HANDLE hProcess = GetCurrentProcess(); + HANDLE hToken; + if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + ShowLastError("NdbMem_Create", "OpenProcessToken"); + } + + Info.Count = 1; + Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + if(!LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid))) + { + ShowLastError("NdbMem_Create", "LookupPrivilegeValue"); + } + + if(!AdjustTokenPrivileges(hToken, FALSE, (PTOKEN_PRIVILEGES)&Info, 0, 0, 0)) + { + ShowLastError("NdbMem_Create", "AdjustTokenPrivileges"); + } + + if(!CloseHandle(hToken)) + { + ShowLastError("NdbMem_Create", "CloseHandle"); + } + + return; +} + +void NdbMem_Destroy() +{ + /* Do nothing */ + return; +} + +void* NdbMem_Allocate(size_t size) +{ + // Address Windowing Extensions + struct AWEINFO* pAWEinfo; + HANDLE hProcess; + SYSTEM_INFO sysinfo; + + if(!gNdbMem_pAWEinfo) + { + gNdbMem_pAWEinfo = VirtualAlloc(0, + sizeof(struct AWEINFO)*cNdbMem_nMaxAWEinfo, + MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + } + + assert(gNdbMem_nAWEinfo < cNdbMem_nMaxAWEinfo); + pAWEinfo = gNdbMem_pAWEinfo+gNdbMem_nAWEinfo++; + + hProcess = GetCurrentProcess(); + GetSystemInfo(&sysinfo); + pAWEinfo->nNumberOfPagesRequested = (size+sysinfo.dwPageSize-1)/sysinfo.dwPageSize; + pAWEinfo->pnPhysicalMemoryPageArray = VirtualAlloc(0, + sizeof(ULONG_PTR)*pAWEinfo->nNumberOfPagesRequested, + MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + pAWEinfo->nNumberOfPagesActual = pAWEinfo->nNumberOfPagesRequested; + if(!AllocateUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesActual), pAWEinfo->pnPhysicalMemoryPageArray)) + { + ShowLastError("NdbMem_Allocate", "AllocateUserPhysicalPages"); + return 0; + } + if(pAWEinfo->nNumberOfPagesRequested != pAWEinfo->nNumberOfPagesActual) + { + ShowLastError("NdbMem_Allocate", "nNumberOfPagesRequested != nNumberOfPagesActual"); + return 0; + } + + pAWEinfo->dwSizeInBytesRequested = size; + pAWEinfo->pRegionReserved = VirtualAlloc(0, pAWEinfo->dwSizeInBytesRequested, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE); + if(!pAWEinfo->pRegionReserved) + { + ShowLastError("NdbMem_Allocate", "VirtualAlloc"); + return 0; + } + + if(!MapUserPhysicalPages(pAWEinfo->pRegionReserved, pAWEinfo->nNumberOfPagesActual, pAWEinfo->pnPhysicalMemoryPageArray)) + { + ShowLastError("NdbMem_Allocate", "MapUserPhysicalPages"); + return 0; + } + + /* + printf("allocate AWE memory: %lu bytes, %lu pages, address %lx\n", + pAWEinfo->dwSizeInBytesRequested, + pAWEinfo->nNumberOfPagesActual, + pAWEinfo->pRegionReserved); + */ + return pAWEinfo->pRegionReserved; +} + + +void* NdbMem_AllocateAlign(size_t size, size_t alignment) +{ + /* + return (void*)memalign(alignment, size); + TEMP fix + */ + return NdbMem_Allocate(size); +} + + +void NdbMem_Free(void* ptr) +{ + // VirtualFree(ptr, 0, MEM_DECOMMIT|MEM_RELEASE); + + // Address Windowing Extensions + struct AWEINFO* pAWEinfo = 0; + size_t i; + HANDLE hProcess; + + for(i=0; i<gNdbMem_nAWEinfo; ++i) + { + if(ptr==gNdbMem_pAWEinfo[i].pRegionReserved) + { + pAWEinfo = gNdbMem_pAWEinfo+i; + } + } + if(!pAWEinfo) + { + ShowLastError("NdbMem_Free", "ptr is not AWE memory"); + } + + hProcess = GetCurrentProcess(); + if(!MapUserPhysicalPages(ptr, pAWEinfo->nNumberOfPagesActual, 0)) + { + ShowLastError("NdbMem_Free", "MapUserPhysicalPages"); + } + + if(!VirtualFree(ptr, 0, MEM_RELEASE)) + { + ShowLastError("NdbMem_Free", "VirtualFree"); + } + + pAWEinfo->nNumberOfPagesFreed = pAWEinfo->nNumberOfPagesActual; + if(!FreeUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesFreed), pAWEinfo->pnPhysicalMemoryPageArray)) + { + ShowLastError("NdbMem_Free", "FreeUserPhysicalPages"); + } + + VirtualFree(pAWEinfo->pnPhysicalMemoryPageArray, 0, MEM_DECOMMIT|MEM_RELEASE); +} + + +int NdbMem_MemLockAll() +{ + /* + HANDLE hProcess = GetCurrentProcess(); + SIZE_T nMinimumWorkingSetSize; + SIZE_T nMaximumWorkingSetSize; + GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize); + ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl; + + SetProcessWorkingSetSize(hProcess, 50000000, 100000000); + + GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize); + ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl; + */ + return -1; +} + +int NdbMem_MemUnlockAll() +{ + //VirtualUnlock(); + return -1; +} + diff --git a/ndb/src/common/portlib/win32/NdbMutex.c b/ndb/src/common/portlib/win32/NdbMutex.c new file mode 100644 index 00000000000..c93384d91db --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbMutex.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <winsock2.h> +#include <ws2tcpip.h> +#include <windows.h> +#include <time.h> +#include <assert.h> + +#include "NdbMutex.h" + + +NdbMutex* NdbMutex_Create(void) +{ + NdbMutex* pNdbMutex = (NdbMutex*)malloc(sizeof(NdbMutex)); + if(!pNdbMutex) + return 0; + + InitializeCriticalSection(pNdbMutex); + return pNdbMutex; +} + + +int NdbMutex_Destroy(NdbMutex* p_mutex) +{ + if(!p_mutex) + return -1; + + DeleteCriticalSection(p_mutex); + free(p_mutex); + return 0; +} + + +int NdbMutex_Lock(NdbMutex* p_mutex) +{ + if(!p_mutex) + return -1; + + EnterCriticalSection (p_mutex); + return 0; +} + + +int NdbMutex_Unlock(NdbMutex* p_mutex) +{ + if(!p_mutex) + return -1; + + LeaveCriticalSection(p_mutex); + return 0; +} + + +int NdbMutex_Trylock(NdbMutex* p_mutex) +{ + int result = -1; + if(p_mutex) + { + result = (TryEnterCriticalSection(p_mutex) ? 0 : -1); + } + return result; +} + diff --git a/ndb/src/common/portlib/win32/NdbSleep.c b/ndb/src/common/portlib/win32/NdbSleep.c new file mode 100644 index 00000000000..ac0f44dd07f --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbSleep.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbSleep.h" + +#include <windows.h> + + +int +NdbSleep_MilliSleep(int milliseconds) +{ + Sleep(milliseconds); + return 0; +} + +int +NdbSleep_SecSleep(int seconds) +{ + return NdbSleep_MilliSleep(seconds*1000); +} + diff --git a/ndb/src/common/portlib/win32/NdbTCP.c b/ndb/src/common/portlib/win32/NdbTCP.c new file mode 100644 index 00000000000..483a53bd606 --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbTCP.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "NdbTCP.h" + +int +Ndb_getInAddr(struct in_addr * dst, const char *address) +{ + struct hostent * hostPtr; + + /* Try it as aaa.bbb.ccc.ddd. */ + dst->s_addr = inet_addr(address); + if (dst->s_addr != -1) { + return 0; + } + + hostPtr = gethostbyname(address); + if (hostPtr != NULL) { + dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr; + return 0; + } + + return -1; +} + diff --git a/ndb/src/common/portlib/win32/NdbThread.c b/ndb/src/common/portlib/win32/NdbThread.c new file mode 100644 index 00000000000..ae3c74be70d --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbThread.c @@ -0,0 +1,118 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <windows.h> +#include <process.h> +#include <assert.h> + +#include "NdbThread.h" + + +#define MAX_THREAD_NAME 16 + +typedef unsigned (WINAPI* NDB_WIN32_THREAD_FUNC)(void*); + + +struct NdbThread +{ + HANDLE hThread; + unsigned nThreadId; + char thread_name[MAX_THREAD_NAME]; +}; + + +struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, + NDB_THREAD_ARG *p_thread_arg, + const NDB_THREAD_STACKSIZE thread_stack_size, + const char* p_thread_name, + NDB_THREAD_PRIO thread_prio) +{ + struct NdbThread* tmpThread; + unsigned initflag; + int nPriority = 0; + + if(!p_thread_func) + return 0; + + tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread)); + if(!tmpThread) + return 0; + + strncpy((char*)&tmpThread->thread_name, p_thread_name, MAX_THREAD_NAME); + + switch(thread_prio) + { + case NDB_THREAD_PRIO_HIGHEST: nPriority=THREAD_PRIORITY_HIGHEST; break; + case NDB_THREAD_PRIO_HIGH: nPriority=THREAD_PRIORITY_ABOVE_NORMAL; break; + case NDB_THREAD_PRIO_MEAN: nPriority=THREAD_PRIORITY_NORMAL; break; + case NDB_THREAD_PRIO_LOW: nPriority=THREAD_PRIORITY_BELOW_NORMAL; break; + case NDB_THREAD_PRIO_LOWEST: nPriority=THREAD_PRIORITY_LOWEST; break; + } + initflag = (nPriority ? CREATE_SUSPENDED : 0); + + tmpThread->hThread = (HANDLE)_beginthreadex(0, thread_stack_size, + (NDB_WIN32_THREAD_FUNC)p_thread_func, p_thread_arg, + initflag, &tmpThread->nThreadId); + + if(nPriority && tmpThread->hThread) + { + SetThreadPriority(tmpThread->hThread, nPriority); + ResumeThread (tmpThread->hThread); + } + + assert(tmpThread->hThread); + return tmpThread; +} + + +void NdbThread_Destroy(struct NdbThread** p_thread) +{ + CloseHandle((*p_thread)->hThread); + (*p_thread)->hThread = 0; + free(*p_thread); + *p_thread = 0; +} + + +int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status) +{ + void *local_status = 0; + if (status == 0) + status = &local_status; + + if(WaitForSingleObject(p_wait_thread->hThread, INFINITE) == WAIT_OBJECT_0 + && GetExitCodeThread(p_wait_thread->hThread, (LPDWORD)status)) + { + CloseHandle(p_wait_thread->hThread); + p_wait_thread->hThread = 0; + return 0; + } + return -1; +} + + +void NdbThread_Exit(int status) +{ + _endthreadex((DWORD) status); +} + + +int NdbThread_SetConcurrencyLevel(int level) +{ + return 0; +} + diff --git a/ndb/src/common/portlib/win32/NdbTick.c b/ndb/src/common/portlib/win32/NdbTick.c new file mode 100644 index 00000000000..e3a67d8437d --- /dev/null +++ b/ndb/src/common/portlib/win32/NdbTick.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <windows.h> +#include "NdbTick.h" + +/* +#define FILETIME_PER_MICROSEC 10 +#define FILETIME_PER_MILLISEC 10000 +#define FILETIME_PER_SEC 10000000 + + +NDB_TICKS NdbTick_CurrentMillisecond(void) +{ + ULONGLONG ullTime; + GetSystemTimeAsFileTime((LPFILETIME)&ullTime); + return (ullTime / FILETIME_PER_MILLISEC); +} + +int +NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros) +{ + ULONGLONG ullTime; + GetSystemTimeAsFileTime((LPFILETIME)&ullTime); + *secs = (ullTime / FILETIME_PER_SEC); + *micros = (Uint32)((ullTime % FILETIME_PER_SEC) / FILETIME_PER_MICROSEC); + return 0; +} +*/ + + +NDB_TICKS NdbTick_CurrentMillisecond(void) +{ + LARGE_INTEGER liCount, liFreq; + QueryPerformanceCounter(&liCount); + QueryPerformanceFrequency(&liFreq); + return (liCount.QuadPart*1000) / liFreq.QuadPart; +} + +int +NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros) +{ + LARGE_INTEGER liCount, liFreq; + QueryPerformanceCounter(&liCount); + QueryPerformanceFrequency(&liFreq); + *secs = liCount.QuadPart / liFreq.QuadPart; + liCount.QuadPart -= *secs * liFreq.QuadPart; + *micros = (liCount.QuadPart*1000000) / liFreq.QuadPart; + return 0; +} |