Example #1
0
File: dll.c Project: TC01/gcc4ti
__ATTR_LIB_C__ short LoadDLL(const char *DLL_name, long ID, short major, short minor)
{
  SYM_ENTRY *entry;
  HANDLE h;
  unsigned char *bptr,*sptr;
  unsigned short len,offset=0,wrongver=0;
  unsigned long pc;
  unsigned long signature[]={__DLL_SIGNATURE,ID};
  asm volatile("bsr 0f; 0:move.l (%%sp)+,%0":"=g"(pc));
  if(HW_VERSION==2 && pc<0x40000) return DLL_NOTINGHOSTSPACE;
  if(__DLL_body_ptr) return DLL_ALREADYLOADED;
  entry=SymFindFirst(NULL,2);
  do
    {
      if(!strcmp(entry->name,DLL_name)&&entry->handle&&!entry->flags.bits.twin
        &&(entry->flags.bits.archived||!HeapGetLock(entry->handle)))
          {
            len=peek_w(bptr=HeapDeref(entry->handle))+2;
            if(!memcmp(bptr+len-5,"DLL\x00\xF8",5))
              {
                offset=0;
                for(sptr=bptr+2;(sptr<bptr+len-1)&&!offset;sptr+=2)
                  if(!memcmp(sptr,signature,8))
                    {
                      if((unsigned short)major!=((__DLL_interface_struct*)sptr)->major
                        ||(unsigned short)minor>((__DLL_interface_struct*)sptr)->minor)
                          wrongver=1;
                      else
                        offset=sptr-bptr,wrongver=0;
                    }
                  if(offset) break;
                }
          }
    } while((entry=SymFindNext()));
  if(wrongver) return DLL_WRONGVERSION;
  if(!entry) return DLL_NOTFOUND;
  if(!HeapLock(h=entry->handle)) return DLL_LOCKFAILED;
  if(!(__DLL_body_ptr=malloc(len=peek_w(bptr=HeapDeref(h)+2)+2))) 
    {
      HeapUnlock(h);
      return DLL_OUTOFMEM;
    }
  memcpy(__DLL_body_ptr,bptr,len);
  EX_patch((char*)__DLL_body_ptr+(HW_VERSION==2?0x40000:0)+2,(char*)__DLL_body_ptr+(HW_VERSION==2?0x40000:0)+len-1);
  __DLL_interface_ptr=(__DLL_interface_struct*)((char*)__DLL_body_ptr+offset-2);
  HeapUnlock(h);
  return DLL_OK;
}
Example #2
0
File: fputc.c Project: TC01/gcc4ti
__ATTR_TIOS_CALLBACK__ short fputc(short c, FILE *f)
{
  short tmode=!(f->flags&_F_BIN);
  unsigned short minalloc;
  char *base=f->base,*oldbase=base;
  if(f->flags&_F_ERR) return EOF;
  if(!(f->flags&_F_WRIT)) __FERROR(f);
  minalloc=peek_w(base)+3;
  if(minalloc>65520u) __FERROR(f);
  if(minalloc>f->alloc)
    {
      HeapUnlock(f->handle);
      if(f->alloc<=65520u-f->buffincrement) f->alloc+=f->buffincrement;
      else f->alloc=65520u;
      if(!HeapRealloc(f->handle,f->alloc)) __FERROR(f);
      base=f->base=HLock(f->handle);
      f->fpos+=base-oldbase;
      oldbase=base;
    }
  if(feof(f)) (*(short*)base)++;
  if(c=='\n'&&tmode) c='\r';
  poke(f->fpos++,c);
  if(c=='\r'&&tmode) fputc(' ',f);
  if(base+peek_w(base)+(tmode?0:2)==f->fpos)
    {
      f->flags|=_F_EOF;
      if(tmode)
        {
          poke(f->fpos,0);
          poke(f->fpos+1,0xE0);
        }
    }
  return c;
}
Example #3
0
void __cdecl xf_dump_chk()
{
#ifndef CONEMU_MINIMAL
	PROCESS_HEAP_ENTRY ent = {NULL};
	HeapLock(ghHeap);
	//HeapCompact(ghHeap,0);
	char sBlockInfo[255];
	PVOID pLast = NULL;

	while(HeapWalk(ghHeap, &ent))
	{
		if (pLast == ent.lpData)
		{
			msprintf(sBlockInfo, countof(sBlockInfo), "!!! HeapWalk cycled at 0x%08X, size=0x%08X\n", (DWORD)ent.lpData, ent.cbData);
			OutputDebugStringA(sBlockInfo);
			_ASSERTE(pLast != ent.lpData);
			break;
		}

		if (((int)ent.cbData) < 0)
		{
			msprintf(sBlockInfo, countof(sBlockInfo), "!!! Invalid memory block size at 0x%08X, size=0x%08X\n", (DWORD)ent.lpData, ent.cbData);
			OutputDebugStringA(sBlockInfo);
			_ASSERTE(((int)ent.cbData) >= 0);
			break;
		}
	}

	HeapUnlock(ghHeap);
#endif
}
Example #4
0
/* Free select data */
void select_data_free (LPSELECTDATA lpSelectData)
{
  DWORD i;

#ifdef DBUG
  dbug_print("Freeing data of %x", lpSelectData);
#endif

  /* Free APC related data, if they exists */
  if (lpSelectData->lpWorker != NULL)
  {
    worker_job_finish(lpSelectData->lpWorker);
    lpSelectData->lpWorker = NULL;
  };

  /* Make sure results/queries cannot be accessed */
  lpSelectData->nResultsCount = 0;
  lpSelectData->nQueriesCount = 0;

  if (!HeapLock(GetProcessHeap()))
  {
    win32_maperr(GetLastError());
    uerror("select_data_free", Nothing);
  };
  HeapFree(GetProcessHeap(), 0, lpSelectData);
  HeapUnlock(GetProcessHeap());
}
Example #5
0
/* Create data associated with a  select operation */
LPSELECTDATA select_data_new (LPSELECTDATA lpSelectData, SELECTTYPE EType)
{
  /* Allocate the data structure */
  LPSELECTDATA res;
  DWORD        i;
  
  if (!HeapLock(GetProcessHeap()))
  {
    win32_maperr(GetLastError());
    uerror("select", Nothing);
  }
  res = (LPSELECTDATA)HeapAlloc(GetProcessHeap(), 0, sizeof(SELECTDATA)); 
  HeapUnlock(GetProcessHeap());

  /* Init common data */
  list_init((LPLIST)res);
  list_next_set((LPLIST)res, (LPLIST)lpSelectData);
  res->EType         = EType;
  res->nResultsCount = 0;
        

  /* Data following are dedicated to APC like call, they
     will be initialized if required. For now they are set to 
     invalid values.
     */
  res->funcWorker    = NULL;
  res->nQueriesCount = 0;
  res->EState        = SELECT_STATE_NONE;
  res->nError        = 0;
  res->lpWorker  = NULL;

  return res;
}
Example #6
0
LPWORKER worker_new (void)
{
  LPWORKER lpWorker = NULL;

  if (!HeapLock(hWorkerHeap))
  {
    win32_maperr(GetLastError());
    uerror("worker_new", Nothing);
  };
  lpWorker = (LPWORKER)HeapAlloc(hWorkerHeap, 0, sizeof(WORKER));
  HeapUnlock(hWorkerHeap);
  list_init((LPLIST)lpWorker);
  lpWorker->hJobStarted  = CreateEvent(NULL, TRUE, FALSE, NULL);
  lpWorker->hJobStop     = CreateEvent(NULL, TRUE, FALSE, NULL);
  lpWorker->hJobDone     = CreateEvent(NULL, TRUE, FALSE, NULL);
  lpWorker->lpJobUserData = NULL;
  lpWorker->hWorkerReady       = CreateEvent(NULL, FALSE, FALSE, NULL);
  lpWorker->hCommandReady      = CreateEvent(NULL, FALSE, FALSE, NULL);
  lpWorker->ECommand           = WORKER_CMD_NONE;
  lpWorker->hThread = CreateThread(
    NULL, 
    THREAD_WORKERS_MEM, 
    worker_wait, 
    (LPVOID)lpWorker, 
    0, 
    NULL);

  return lpWorker;
};
Example #7
0
void __cdecl xf_dump()
{
	PROCESS_HEAP_ENTRY ent = {NULL};
	HeapLock(ghHeap);
	HeapCompact(ghHeap,0);
	char sBlockInfo[255];
	while (HeapWalk(ghHeap, &ent))
	{
		if (ent.wFlags & PROCESS_HEAP_ENTRY_BUSY) {
			xf_mem_block* p = (xf_mem_block*)ent.lpData;
			if (p->bBlockUsed==TRUE && p->nBlockSize==ent.cbData)
			{
#ifndef _WIN64
				wsprintfA(sBlockInfo, "!!! Lost memory block at 0x%08X, size %u\n    Allocated from: %s\n", ent.lpData, ent.cbData,
					p->sCreatedFrom);
#else
				wsprintfA(sBlockInfo, "!!! Lost memory block at 0x%I64X, size %u\n    Allocated from: %s\n", ent.lpData, ent.cbData,
					p->sCreatedFrom);
#endif
			} else {
#ifndef _WIN64
				wsprintfA(sBlockInfo, "!!! Lost memory block at 0x%08X, size %u\n    Allocated from: %s\n", ent.lpData, ent.cbData,
					"<Header information broken!>");
#else
				wsprintfA(sBlockInfo, "!!! Lost memory block at 0x%I64X, size %u\n    Allocated from: %s\n", ent.lpData, ent.cbData,
					"<Header information broken!>");
#endif
			}
			OutputDebugStringA(sBlockInfo);
		}
	}
	HeapUnlock(ghHeap);
}
Example #8
0
int hprintf(HANDLE h, const char *fmt, ...)
{
    /* WriteFile is *not* atomic after a 512 byte boundary, we need to lock */
    static CRITICAL_SECTION sync;
    static int init = 0;

    /* We use the heap lock to assure mutual exclusion during initialization */
    if (!init) {
        HANDLE heap = GetProcessHeap();
        if (!HeapLock(heap))
            panic("Could not lock the global heap lock");

        if (!init) {
            InitializeCriticalSection(&sync);
            init = 1;
        }

        if (!HeapUnlock(heap))
            panic("Could not unlock the global heap lock");
    }

    int sz;
    char *buf = NULL;
    va_list vl;
    va_list vlc;

    va_start(vl, fmt);
    va_copy(vlc, vl);
    sz = _vscprintf(fmt, vlc);
    va_end(vlc);

    int rc = -1;
    if (sz <= 0)
        goto end;
    ++sz;

    buf = (char*)malloc(sz);
    if (!buf)
        goto end;

    rc = vsnprintf(buf, sz, fmt, vl);
    if (rc <= 0)
        goto end;

    DWORD written;

    EnterCriticalSection(&sync);
    if (!WriteFile(h, buf, rc, &written, NULL)) {
        rc = -1;
        errno = EIO;
    } else {
        rc = written;
    }
    LeaveCriticalSection(&sync);
    
end:
    free(buf);
    va_end(vl);
    return rc;
}
Example #9
0
void* prim_heapUnlock(HANDLE arg1)
{ static struct {HsInt gc_failed;HsPtr gc_failstring;} gc_result;
  int gc_failed;
  char* gc_failstring;
  do { BOOL res1=HeapUnlock(arg1);
      if ((gc_failed = ( res1==0 ))) {gc_failstring = ErrorWin("HeapUnlock") ;}
      else {gc_failed = 0;}
      gc_result.gc_failed = gc_failed;
      gc_result.gc_failstring = gc_failstring;
      
      return(&gc_result);} while(0);
}
Example #10
0
BOOL WINAPI HeapSafeFree(_Inout_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ _Post_ptr_invalid_ LPVOID lpMem)
{
	SIZE_T cbMem;
	BOOL res;

	if (!hHeap || !lpMem)
		return FALSE;

	if (!HeapLock(hHeap))
		return FALSE;

	cbMem = HeapSize(hHeap, dwFlags, lpMem);
	if (cbMem > 0 && cbMem != (SIZE_T)-1)
		SecureZeroMemory(lpMem, cbMem);

	res = HeapFree(hHeap, dwFlags, lpMem);

	HeapUnlock(hHeap);

	return res;
}
Example #11
0
guint
gum_peek_private_memory_usage (void)
{
  guint total_size = 0;
  BOOL success;
  PROCESS_HEAP_ENTRY entry;

  success = HeapLock (_gum_memory_heap);
  g_assert (success);

  entry.lpData = NULL;
  while (HeapWalk (_gum_memory_heap, &entry) != FALSE)
  {
    if ((entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0)
      total_size += entry.cbData;
  }

  success = HeapUnlock (_gum_memory_heap);
  g_assert (success);

  return total_size;
}
Example #12
0
bool winstd::heap::enumerate()
{
    assert(m_h != invalid);

    bool found = false;

    // Lock the heap for exclusive access.
    HeapLock(m_h);

    PROCESS_HEAP_ENTRY e;
    e.lpData = NULL;
    while (HeapWalk(m_h, &e) != FALSE) {
        if ((e.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
            OutputDebugStr(
                _T("Allocated block%s%s\n")
                _T("  Data portion begins at: %#p\n  Size: %d bytes\n")
                _T("  Overhead: %d bytes\n  Region index: %d\n"),
                    (e.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0 ? tstring_printf(_T(", movable with HANDLE %#p"), e.Block.hMem).c_str() : _T(""),
                    (e.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0 ? _T(", DDESHARE") : _T(""),
                     e.lpData,
                     e.cbData,
                     e.cbOverhead,
                     e.iRegionIndex);

            found = true;
        }
    }

    DWORD dwResult = GetLastError();
    if (dwResult != ERROR_NO_MORE_ITEMS)
        OutputDebugStr(_T("HeapWalk failed (error %u).\n"), dwResult);

    // Unlock the heap.
    HeapUnlock(m_h);

    return found;
}
Example #13
0
void SaveHeapLog()
{
  FILE *f;
  _HEAPINFO hi;
  char block[129],*ad;
  block[128]=0;
  int code;
  HANDLE heaps[200];
  DWORD n;
  PROCESS_HEAP_ENTRY phe;

  f=fopen(WriteDir+SLASH+"heap.log","wb");

  SetLastError(0);
  n=GetProcessHeaps(200,heaps);
  heaps[n]=GetProcessHeap();n++;
  fprintf(f,"There are %i heaps for Steem\r\n",n);
  for (DWORD i=0;i<n;i++){
    code=HeapValidate(heaps[i],0,NULL);
    if (code){
      fprintf(f,"Heap %u okay\r\n",i);
    }else{
      fprintf(f,"Heap %u has an error in it!\r\n",i);
    }
    HeapLock(heaps[i]);
    phe.lpData=NULL;
    while (HeapWalk(heaps[i],&phe)){
      fprintf(f,"%s%X\r\n","Bad node, address=",(unsigned long)(phe.lpData));
      ad=((char*)phe.lpData)-64;
      for (int n=0;n<128;n++){
        block[n]=*(ad++);
        if (block[n]==0) block[n]='\\';
        if (block[n]==10) block[n]='\\';
        if (block[n]==13) block[n]='\\';
      }
      fprintf(f,"%s\r\n",block);
    }
    HeapUnlock(heaps[i]);
    if (phe.lpData==NULL) DisplayLastError();
  }

  fprintf(f,"\r\n\r\n");
  code=_heapchk();
  if (code==_HEAPOK){
    fprintf(f,"%s\r\n","Heap okay, walking:");
  }else if (code==_HEAPBADNODE){
    fprintf(f,"%s\r\n","Heap has bad node! Walking anyway:");
  }
  hi._pentry=NULL;
  for(;;){
    code=_rtl_heapwalk(&hi);
    if (code==_HEAPEND) break;
    if (code==_HEAPBADNODE){
      fprintf(f,"%s%X\r\n","Bad node, address=",(unsigned long)(hi.__pentry));
      ad=((char*)hi._pentry)-64;
      for (int n=0;n<128;n++){
        block[n]=*(ad++);
        if (block[n]==0) block[n]='\\';
        if (block[n]==10) block[n]='\\';
        if (block[n]==13) block[n]='\\';
      }
      fprintf(f,"%s\r\n",block);
    }else if (code==_HEAPOK){
      fprintf(f,"%s%X\r\n","Good node, address=",(unsigned long)(hi.__pentry));
    }
  }
  fclose(f);
}
Example #14
0
void	TLMemory::Platform::MemOuputAllocations()
{
	DWORD LastError;
	PROCESS_HEAP_ENTRY Entry;

	TChar buffer[256] = {0};

    // Lock the heap to prevent other threads from accessing the heap 
    // during enumeration.
    if (HeapLock(g_MemHeap) == FALSE) {
        _stprintf(&buffer[0], TEXT("Failed to lock heap with LastError %d.\n"),
                 GetLastError());

		OutputDebugString(buffer);
        return;
    }

    _stprintf(&buffer[0], TEXT("Walking heap %#p...\n\n"), g_MemHeap);
	OutputDebugString(buffer);

    Entry.lpData = NULL;
    while (HeapWalk(g_MemHeap, &Entry) != FALSE) 
	{
        if ((Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) 
		{
            _stprintf(&buffer[0], TEXT("Allocated block"));
			OutputDebugString(buffer);

            if ((Entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0) 
			{
                _stprintf(&buffer[0], TEXT(", movable with HANDLE %#p"), Entry.Block.hMem);
				OutputDebugString(buffer);
            }

            if ((Entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0) 
			{
                _stprintf(&buffer[0], TEXT(", DDESHARE"));
				OutputDebugString(buffer);
            }
        }
        else if ((Entry.wFlags & PROCESS_HEAP_REGION) != 0) 
		{
            _stprintf(&buffer[0], TEXT("Region\n  %d bytes committed\n") \
                     TEXT("  %d bytes uncommitted\n  First block address: %#p\n") \
                     TEXT("  Last block address: %#p\n"),
                     Entry.Region.dwCommittedSize,
                     Entry.Region.dwUnCommittedSize,
                     Entry.Region.lpFirstBlock,
                     Entry.Region.lpLastBlock);
			OutputDebugString(buffer);
        }
        else if ((Entry.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) != 0) 
		{
            _stprintf(&buffer[0], TEXT("Uncommitted range\n"));
			OutputDebugString(buffer);
        }
        else 
		{
            _stprintf(&buffer[0], TEXT("Block\n"));
			OutputDebugString(buffer);
        }

        _stprintf(&buffer[0], TEXT("  Data portion begins at: %#p\n  Size: %d bytes\n") \
                 TEXT("  Overhead: %d bytes\n  Region index: %d\n\n"),
                 Entry.lpData,
                 Entry.cbData,
                 Entry.cbOverhead,
                 Entry.iRegionIndex);
		OutputDebugString(buffer);
    }
    LastError = GetLastError();
    if (LastError != ERROR_NO_MORE_ITEMS) 
	{
        _stprintf(&buffer[0], TEXT("HeapWalk failed with LastError %d.\n"), LastError);
		OutputDebugString(buffer);
    }

    //
    // Unlock the heap to allow other threads to access the heap after 
    // enumeration has completed.
    //
    if (HeapUnlock(g_MemHeap) == FALSE) 
	{
        _stprintf(&buffer[0], TEXT("Failed to unlock heap with LastError %d.\n"),
                 GetLastError());
		OutputDebugString(buffer);
    }
}
Example #15
0
void worker_free (LPWORKER lpWorker)
{
  /* Wait for termination of the worker */
#ifdef DBUG
  dbug_print("Shutting down worker %x", lpWorker);
#endif
  WaitForSingleObject(lpWorker->hWorkerReady, INFINITE);
  lpWorker->ECommand = WORKER_CMD_STOP;
  SetEvent(lpWorker->hCommandReady);
  WaitForSingleObject(lpWorker->hThread, INFINITE);

  /* Free resources */
#ifdef DBUG
  dbug_print("Freeing resources of worker %x", lpWorker);
#endif
  if (lpWorker->hThread != INVALID_HANDLE_VALUE)
  {
    CloseHandle(lpWorker->hThread);
    lpWorker->hThread = INVALID_HANDLE_VALUE;
  }

  if (lpWorker->hJobStarted != INVALID_HANDLE_VALUE)
  {
    CloseHandle(lpWorker->hJobStarted);
    lpWorker->hJobStarted = INVALID_HANDLE_VALUE;
  }

  if (lpWorker->hJobStop != INVALID_HANDLE_VALUE)
  {
    CloseHandle(lpWorker->hJobStop);
    lpWorker->hJobStop = INVALID_HANDLE_VALUE;
  }

  if (lpWorker->hJobDone != INVALID_HANDLE_VALUE)
  {
    CloseHandle(lpWorker->hJobDone);
    lpWorker->hJobDone = INVALID_HANDLE_VALUE;
  }

  lpWorker->lpJobUserData = NULL;
  lpWorker->hJobFunc = NULL;

  if (lpWorker->hWorkerReady != INVALID_HANDLE_VALUE)
  {
    CloseHandle(lpWorker->hWorkerReady);
    lpWorker->hWorkerReady = INVALID_HANDLE_VALUE;
  }

  if (lpWorker->hCommandReady != INVALID_HANDLE_VALUE)
  {
    CloseHandle(lpWorker->hCommandReady);
    lpWorker->hCommandReady = INVALID_HANDLE_VALUE;
  }

  if (!HeapLock(hWorkerHeap))
  {
    win32_maperr(GetLastError());
    uerror("worker_new", Nothing);
  };
  HeapFree(hWorkerHeap, 0, lpWorker);
  HeapUnlock(hWorkerHeap);
};
Example #16
0
void __cdecl xf_dump()
{
#ifndef CONEMU_MINIMAL
	PROCESS_HEAP_ENTRY ent = {NULL};
	HeapLock(ghHeap);
	//HeapCompact(ghHeap,0);
	char sBlockInfo[255];
	PVOID pLast = NULL;
	size_t cbUsedSize = 0, cbBrokenSize = 0;
	DWORD cCount = 0;

	while (HeapWalk(ghHeap, &ent))
	{
		if (pLast == ent.lpData)
		{
			msprintf(sBlockInfo, countof(sBlockInfo), "!!! HeapWalk cycled at 0x%08X, size=0x%08X\n", (DWORD)ent.lpData, ent.cbData);
			OutputDebugStringA(sBlockInfo);
			_ASSERTE(pLast != ent.lpData);
			break;
		}

		if (((int)ent.cbData) < 0)
		{
			msprintf(sBlockInfo, countof(sBlockInfo), "!!! Invalid memory block size at 0x%08X, size=0x%08X\n", (DWORD)ent.lpData, ent.cbData);
			OutputDebugStringA(sBlockInfo);
			_ASSERTE(((int)ent.cbData) >= 0);
			break;
		}

		if (ent.wFlags & PROCESS_HEAP_ENTRY_BUSY)
		{
			xf_mem_block* p = (xf_mem_block*)ent.lpData;

			if (p->bBlockUsed==TRUE && (p->nBlockSize+sizeof(xf_mem_block)+8)==ent.cbData)
			{
				msprintf(sBlockInfo, countof(sBlockInfo), "Used memory block at 0x" WIN3264TEST("%08X","%08X%08X") ", size %u\n    Allocated from: %s\n", WIN3264WSPRINT(ent.lpData), ent.cbData,
				          p->sCreatedFrom);

				cbUsedSize += p->nBlockSize;
			}
			else
			{
				msprintf(sBlockInfo, countof(sBlockInfo), "Used memory block at 0x" WIN3264TEST("%08X","%08X%08X") ", size %u\n    Allocated from: %s\n", WIN3264WSPRINT(ent.lpData), ent.cbData,
				          "<Header information broken!>");

				cbBrokenSize += ent.cbData;
			}

			cCount++;

			pLast = ent.lpData;
			OutputDebugStringA(sBlockInfo);
		}
	}

	HeapUnlock(ghHeap);

	msprintf(sBlockInfo, countof(sBlockInfo), "Used size 0x" WIN3264TEST("%08X","%08X%08X") ", broken size 0x" WIN3264TEST("%08X","%08X%08X") ", total blocks %u\n",
		WIN3264WSPRINT(cbUsedSize), WIN3264WSPRINT(cbBrokenSize), cCount);
	OutputDebugStringA(sBlockInfo);
#endif
}
Example #17
0
CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value timeout)
{  
  /* Event associated to handle */
  DWORD   nEventsCount;
  DWORD   nEventsMax;
  HANDLE *lpEventsDone;
  
  /* Data for all handles */
  LPSELECTDATA lpSelectData;
  LPSELECTDATA iterSelectData;

  /* Iterator for results */
  LPSELECTRESULT iterResult;

  /* Iterator */
  DWORD i;

  /* Error status */
  DWORD err;

  /* Time to wait */
  DWORD milliseconds;

  /* Is there static select data */
  BOOL  hasStaticData = FALSE;

  /* Wait return */
  DWORD waitRet;

  /* Set of handle */
  SELECTHANDLESET hds;
  DWORD           hdsMax;
  LPHANDLE        hdsData;

  /* Length of each list */
  DWORD readfds_len;
  DWORD writefds_len;
  DWORD exceptfds_len;

  CAMLparam4 (readfds, writefds, exceptfds, timeout);
  CAMLlocal5 (read_list, write_list, except_list, res, l);
  CAMLlocal1 (fd);

#ifdef DBUG
  dbug_print("in select");
#endif

  nEventsCount   = 0;
  nEventsMax     = 0;
  lpEventsDone   = NULL;
  lpSelectData   = NULL;
  iterSelectData = NULL;
  iterResult     = NULL;
  err            = 0;
  hasStaticData  = 0;
  waitRet        = 0;
  readfds_len    = caml_list_length(readfds);
  writefds_len   = caml_list_length(writefds);
  exceptfds_len  = caml_list_length(exceptfds);
  hdsMax         = MAX(readfds_len, MAX(writefds_len, exceptfds_len));

  if (!HeapLock(GetProcessHeap()))
  {
    win32_maperr(GetLastError());
    uerror("select", Nothing);
  }
  hdsData = (HANDLE *)HeapAlloc(
      GetProcessHeap(), 
      0, 
      sizeof(HANDLE) * hdsMax);
  HeapUnlock(GetProcessHeap());

  if (Double_val(timeout) >= 0.0)
  {
    milliseconds = 1000 * Double_val(timeout);
#ifdef DBUG
    dbug_print("Will wait %d ms", milliseconds);
#endif
  }
  else
  {
    milliseconds = INFINITE;
  }


  /* Create list of select data, based on the different list of fd to watch */
#ifdef DBUG
  dbug_print("Dispatch read fd");
#endif
  handle_set_init(&hds, hdsData, hdsMax);
  for (l = readfds; l != Val_int(0); l = Field(l, 1))
  {
    fd = Field(l, 0);
    if (!handle_set_mem(&hds, Handle_val(fd)))
    {
      handle_set_add(&hds, Handle_val(fd));
      lpSelectData = select_data_dispatch(lpSelectData, SELECT_MODE_READ, fd);
    }
    else
    {
#ifdef DBUG
      dbug_print("Discarding handle %x which is already monitor for read", Handle_val(fd));
#endif
    }
  }
  handle_set_reset(&hds);

#ifdef DBUG
  dbug_print("Dispatch write fd");
#endif
  handle_set_init(&hds, hdsData, hdsMax);
  for (l = writefds; l != Val_int(0); l = Field(l, 1))
  {
    fd = Field(l, 0);
    if (!handle_set_mem(&hds, Handle_val(fd)))
    {
      handle_set_add(&hds, Handle_val(fd));
      lpSelectData = select_data_dispatch(lpSelectData, SELECT_MODE_WRITE, fd);
    }
    else
    {
#ifdef DBUG
      dbug_print("Discarding handle %x which is already monitor for write", Handle_val(fd));
#endif
    }
  }
  handle_set_reset(&hds);

#ifdef DBUG
  dbug_print("Dispatch exceptional fd");
#endif
  handle_set_init(&hds, hdsData, hdsMax);
  for (l = exceptfds; l != Val_int(0); l = Field(l, 1))
  {
    fd = Field(l, 0);
    if (!handle_set_mem(&hds, Handle_val(fd)))
    {
      handle_set_add(&hds, Handle_val(fd));
      lpSelectData = select_data_dispatch(lpSelectData, SELECT_MODE_EXCEPT, fd);
    }
    else
    {
#ifdef DBUG
      dbug_print("Discarding handle %x which is already monitor for exceptional", Handle_val(fd));
#endif
    }
  }
  handle_set_reset(&hds);

  /* Building the list of handle to wait for */
#ifdef DBUG
  dbug_print("Building events done array");
#endif
  nEventsMax   = list_length((LPLIST)lpSelectData);
  nEventsCount = 0;
  if (!HeapLock(GetProcessHeap()))
  {
    win32_maperr(GetLastError());
    uerror("select", Nothing);
  }
  lpEventsDone = (HANDLE *)HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLE) * nEventsMax);
  HeapUnlock(GetProcessHeap());

  iterSelectData = lpSelectData;
  while (iterSelectData != NULL)
  {
    /* Check if it is static data. If this is the case, launch everything
     * but don't wait for events. It helps to test if there are events on
     * any other fd (which are not static), knowing that there is at least
     * one result (the static data).
     */
    if (iterSelectData->EType == SELECT_TYPE_STATIC)
    {
      hasStaticData = TRUE;
    };

    /* Execute APC */
    if (iterSelectData->funcWorker != NULL)
    {
      iterSelectData->lpWorker = 
        worker_job_submit(
            iterSelectData->funcWorker, 
            (void *)iterSelectData);
#ifdef DBUG
      dbug_print("Job submitted to worker %x", iterSelectData->lpWorker); 
#endif
      lpEventsDone[nEventsCount] = worker_job_event_done(iterSelectData->lpWorker);
      nEventsCount++;
    };
    iterSelectData = LIST_NEXT(LPSELECTDATA, iterSelectData);
  };

#ifdef DBUG
  dbug_print("Need to watch %d workers", nEventsCount);
#endif

  /* Processing select itself */
  enter_blocking_section();
  /* There are worker started, waiting to be monitored */
  if (nEventsCount > 0)
  {
    /* Waiting for event */
    if (err == 0 && !hasStaticData)
    {
#ifdef DBUG
      dbug_print("Waiting for one select worker to be done");
#endif
      switch (WaitForMultipleObjects(nEventsCount, lpEventsDone, FALSE, milliseconds))
      {
        case WAIT_FAILED:
          err = GetLastError();
          break;

        case WAIT_TIMEOUT:
#ifdef DBUG
          dbug_print("Select timeout");
#endif
          break;

        default:
#ifdef DBUG
          dbug_print("One worker is done");
#endif
          break;
      };
    }

    /* Ordering stop to every worker */
#ifdef DBUG
    dbug_print("Sending stop signal to every select workers");
#endif
    iterSelectData = lpSelectData;
    while (iterSelectData != NULL)
    {
      if (iterSelectData->lpWorker != NULL)
      {
        worker_job_stop(iterSelectData->lpWorker);
      };
      iterSelectData = LIST_NEXT(LPSELECTDATA, iterSelectData);
    };
      
#ifdef DBUG
    dbug_print("Waiting for every select worker to be done");
#endif
    switch (WaitForMultipleObjects(nEventsCount, lpEventsDone, TRUE, INFINITE))
    {
      case WAIT_FAILED:
        err = GetLastError();
        break;

      default:
#ifdef DBUG
        dbug_print("Every worker is done");
#endif
        break;
    }
  }
  /* Nothing to monitor but some time to wait. */
  else if (!hasStaticData)
  {
    Sleep(milliseconds);
  }
  leave_blocking_section();

#ifdef DBUG
  dbug_print("Error status: %d (0 is ok)", err);
#endif
  /* Build results */
  if (err == 0)
  {
#ifdef DBUG
    dbug_print("Building result");
#endif
    read_list = Val_unit; 
    write_list = Val_unit;
    except_list = Val_unit;

    iterSelectData = lpSelectData;
    while (iterSelectData != NULL)
    {
      for (i = 0; i < iterSelectData->nResultsCount; i++)
      {
        iterResult = &(iterSelectData->aResults[i]);
        l = alloc_small(2, 0);
        Store_field(l, 0, (value)iterResult->lpOrig);
        switch (iterResult->EMode)
        {
        case SELECT_MODE_READ:
          Store_field(l, 1, read_list);
          read_list = l;
          break;
        case SELECT_MODE_WRITE:
          Store_field(l, 1, write_list);
          write_list = l;
          break;
        case SELECT_MODE_EXCEPT:
          Store_field(l, 1, except_list);
          except_list = l;
          break;
        }
      }
      /* We try to only process the first error, bypass other errors */
      if (err == 0 && iterSelectData->EState == SELECT_STATE_ERROR)
      {
        err = iterSelectData->nError;
      }
      iterSelectData = LIST_NEXT(LPSELECTDATA, iterSelectData);
    }
  }

  /* Free resources */
#ifdef DBUG
  dbug_print("Free selectdata resources");
#endif
  iterSelectData = lpSelectData;
  while (iterSelectData != NULL)
  {
    lpSelectData = iterSelectData;
    iterSelectData = LIST_NEXT(LPSELECTDATA, iterSelectData);
    select_data_free(lpSelectData);
  }
  lpSelectData = NULL;
  
  /* Free allocated events/handle set array */
#ifdef DBUG
  dbug_print("Free local allocated resources");
#endif
  if (!HeapLock(GetProcessHeap()))
  {
    win32_maperr(GetLastError());
    uerror("select", Nothing);
  }
  HeapFree(GetProcessHeap(), 0, lpEventsDone);
  HeapFree(GetProcessHeap(), 0, hdsData);
  HeapUnlock(GetProcessHeap());

#ifdef DBUG
  dbug_print("Raise error if required");
#endif
  if (err != 0)
  {
    win32_maperr(err);
    uerror("select", Nothing);
  }

#ifdef DBUG
  dbug_print("Build final result");
#endif
  res = alloc_small(3, 0);
  Store_field(res, 0, read_list);
  Store_field(res, 1, write_list);
  Store_field(res, 2, except_list);

#ifdef DBUG
  dbug_print("out select");
#endif

  CAMLreturn(res);
}