예제 #1
0
파일: heap.c 프로젝트: iXit/wine
/*********************************************************************
 *		_heapmin (MSVCRT.@)
 */
int CDECL _heapmin(void)
{
  if (!HeapCompact( heap, 0 ) ||
          (sb_heap && !HeapCompact( sb_heap, 0 )))
  {
    if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
      msvcrt_set_errno(GetLastError());
    return -1;
  }
  return 0;
}
예제 #2
0
//-------------------------------------------------------------------//
// CompactHeap()																		//
//-------------------------------------------------------------------//
// This function compacts the application's heap(s) and returns
// the maximum block size available after compaction.
//
// Not sure which of the heaps we encounter is the "default" used by
// the program.  We compact them all.
//
// If you want a heap count, provide the address of the integer
// to set.
//
// NOTE: we only allow 25 heaps max here.
//-------------------------------------------------------------------//
unsigned int CompactHeap( int* pnHeapCount )
{
	// This does ALL heaps.
	unsigned int unLargestBlock = 0;
	HANDLE hHeaps[25];
	DWORD dwHeaps = GetProcessHeaps( 25, hHeaps );
	ASSERT( dwHeaps < 25 );
	if ( dwHeaps < 25 )
	{
		for ( int nA = 0; nA < dwHeaps; nA++ )
		{
			unLargestBlock = max( unLargestBlock, HeapCompact( hHeaps[nA], 0 ) );
		}
	}

	if ( pnHeapCount != 0 )
		*pnHeapCount = dwHeaps;

	return unLargestBlock;

	/*
	// This does the default heap (the CRT heap? not according to 
	// M$DN support...).
	return HeapCompact( GetProcessHeap(), 0 );
	*/
}
예제 #3
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);
}
예제 #4
0
int __cdecl _heapmin(void) {
    if ((HeapCompact(_crtheap, 0) == 0) &&
            (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)) {
        return -1;
    }

    return 0;
}
예제 #5
0
void dm_HeapCompact()
{
	HANDLE hHeap;

	if(hHeap = GetProcessHeap())
	{
		HeapCompact(hHeap, 0);
	}
}
예제 #6
0
파일: heap.c 프로젝트: pstrealer/wine
/*********************************************************************
 *		_heapmin (MSVCRT.@)
 */
int CDECL _heapmin(void)
{
  if (!HeapCompact( GetProcessHeap(), 0 ))
  {
    if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
      msvcrt_set_errno(GetLastError());
    return -1;
  }
  return 0;
}
예제 #7
0
static void
SystemProcessTimer()
{
#ifdef _WIN32_WCE
  HeapCompact();
#endif

  SystemClockTimer();

  CheckDisplayTimeOut(false);
}
예제 #8
0
void	xrMemory::mem_compact	()
{
	RegFlushKey						( HKEY_CLASSES_ROOT );
	RegFlushKey						( HKEY_CURRENT_USER );
	if (g_allow_heap_min)
		_heapmin					( );
	HeapCompact					(GetProcessHeap(),0);
	if (g_pStringContainer)			g_pStringContainer->clean		();
	if (g_pSharedMemoryContainer)	g_pSharedMemoryContainer->clean	();
	if (strstr(Core.Params,"-swap_on_compact"))
		SetProcessWorkingSetSize	(GetCurrentProcess(),size_t(-1),size_t(-1));
}
예제 #9
0
void* prim_heapCompact(HANDLE arg1,DWORD arg2)
{ static struct {HsWord32 res1;HsInt gc_failed;HsPtr gc_failstring;} gc_result;
  UINT res1;int gc_failed;
	    char* gc_failstring;
  do {res1 = HeapCompact(arg1, arg2);
      if ((gc_failed = ( res1==NULL ))) {gc_failstring = ErrorWin("HeapCompact") ;}
      else {gc_failed = 0;}
      gc_result.res1 = (UINT)(res1);
      gc_result.gc_failed = gc_failed;
      gc_result.gc_failstring = gc_failstring;
      
      return(&gc_result);} while(0);
}
예제 #10
0
파일: heapmin.c 프로젝트: chunhualiu/OpenNT
int __cdecl _heapmin(void)
{
	if ( HeapCompact( _crtheap, 0 ) == 0 ) {

	    if ( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED ) {
		_doserrno = ERROR_CALL_NOT_IMPLEMENTED;
		errno = ENOSYS;
	    }

	    return -1;
        }
	else {
	    return 0;
        }
}
예제 #11
0
// This is necessary to be called periodically to get rid of
// memory defragmentation, since on pocket pc platforms there is no
// automatic defragmentation.
void MyCompactHeaps() {
#if defined(GNAV) && !defined(__GNUC__)
  HeapCompact(GetProcessHeap(), 0);
#else
  typedef DWORD (_stdcall *CompactAllHeapsFn) (void);
  static CompactAllHeapsFn CompactAllHeaps = NULL;
  static bool init = false;
  if (!init) {
    // get the pointer to the function
    CompactAllHeaps = (CompactAllHeapsFn)GetProcAddress(
        LoadLibrary(_T("coredll.dll")), _T("CompactAllHeaps"));
    init = true;
  }
  if (CompactAllHeaps)
    CompactAllHeaps();
#endif
}
예제 #12
0
/**
 * Allocates the specified number of bytes from the heap.
 * @param flags			Allocation attributes
 * @param size			Number of bytes to allocate
 */
static MEM_NODE *MemoryAlloc(long size) {
	MEM_NODE *pHeap = &heapSentinel;

#ifdef SCUMM_NEED_ALIGNMENT
	const int alignPadding = sizeof(void*) - 1;
	size = (size + alignPadding) & ~alignPadding;	//round up to nearest multiple of sizeof(void*), this ensures the addresses that are returned are alignment-safe.
#endif

	// compact the heap to make up room for 'size' bytes, if necessary
	if (!HeapCompact(size))
		return 0;

	// success! we may allocate a new node of the right size

	// Allocate a node.
	MEM_NODE *pNode = AllocMemNode();

	// Allocate memory for the node.
	pNode->pBaseAddr = (byte *)malloc(size);

	// Verify that we got the memory.
	// TODO: If this fails, we should first try to compact the heap some further.
	assert(pNode->pBaseAddr);

	// Subtract size of new block from total
	heapSentinel.size -= size;

#ifdef DEBUG
	MemoryStats();
#endif

	// Set flags, LRU time and size
	pNode->flags = DWM_USED;
	pNode->lruTime = DwGetCurrentTime() + 1;
	pNode->size = size;

	// set mnode at the end of the list
	pNode->pPrev = pHeap->pPrev;
	pNode->pNext = pHeap;

	// fix links to this mnode
	pHeap->pPrev->pNext = pNode;
	pHeap->pPrev = pNode;

	return pNode;
}
예제 #13
0
파일: malloc.c 프로젝트: hoangduit/reactos
/*
 * @implemented
 */
int	_heapmin(void)
{
	if (!HeapCompact(GetProcessHeap(), 0))
		return -1;
	return 0;
}
예제 #14
0
파일: heapwalk.c 프로젝트: mingpen/OpenNT
int
_cdecl
main()
{
    struct _heapinfo info;
    PROCESS_HEAP_ENTRY Entry;
    size_t i;
    LPBYTE s;

    info._pentry = NULL;
    setvbuf( stdout, MyBuffer, _IOFBF, sizeof( MyBuffer ) );
    _heapset( 0xAE );
    while (_heapwalk( &info ) == _HEAPOK) {
        printf( "%08x: %05x - %s", info._pentry, info._size, info._useflag ? "busy" : "free" );
        if (info._useflag == _FREEENTRY) {
            s = (LPBYTE)info._pentry;
            for (i=0; i<info._size; i++) {
                if (s[i] != 0xAE) {
                    printf( " *** free block invalid at offset %x [%x]", i, s[i] );
                    break;
                    }
                }
            }

        printf( "\n" );
        fflush( stdout );
        }
    printf( "*** end of heap ***\n\n" );
    fflush( stdout );

    NumberOfHeaps = GetProcessHeaps( 64, ProcessHeaps );
    Entry.lpData = NULL;
    for (i=0; i<NumberOfHeaps; i++) {
        printf( "Heap[ %u ]: %x  HeapCompact result: %lx\n",
                i,
                ProcessHeaps[ i ],
                HeapCompact( ProcessHeaps[ i ], 0 )
              );
        while (HeapWalk( ProcessHeaps[ i ], &Entry )) {
            if (Entry.wFlags & PROCESS_HEAP_REGION) {
                printf( "    %08x: %08x - Region(First: %08x  Last: %08x  Committed: %x  Uncommitted: %08x)\n",
                        Entry.lpData, Entry.cbData,
                        Entry.Region.lpFirstBlock,
                        Entry.Region.lpLastBlock,
                        Entry.Region.dwCommittedSize,
                        Entry.Region.dwUnCommittedSize
                      );
                }
            else
            if (Entry.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) {
                printf( "    %08x: %08x - Uncommitted\n",
                        Entry.lpData, Entry.cbData
                      );
                }
            else
            if (Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) {
                printf( "    %08x: %08x - Busy", Entry.lpData, Entry.cbData );
                if (Entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) {
                    printf( "  hMem: %08x", Entry.Block.hMem );
                    }

                if (Entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) {
                    printf( "  DDE" );
                    }

                printf( "\n" );
                }
            else {
                printf( "    %08x: %08x - Free\n", Entry.lpData, Entry.cbData );
                }

            fflush( stdout );
            }

        printf( "*** end of heap ***\n\n" );
        fflush( stdout );
        }

    return 0;
}
예제 #15
0
void theLoop::AcceptUser(AcceptedSocket *AccptSocket) {
    bool bIPv6 = false;

    char sIP[46];

    uint8_t ui128IpHash[16];
    memset(ui128IpHash, 0, 16);

    uint16_t ui16IpTableIdx = 0;

    if(AccptSocket->addr.ss_family == AF_INET6) {
        memcpy(ui128IpHash, &((struct sockaddr_in6 *)&AccptSocket->addr)->sin6_addr.s6_addr, 16);

        if(IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&AccptSocket->addr)->sin6_addr)) {
			in_addr ipv4addr;
			memcpy(&ipv4addr, ((struct sockaddr_in6 *)&AccptSocket->addr)->sin6_addr.s6_addr + 12, 4);
			strcpy(sIP, inet_ntoa(ipv4addr));

            ui16IpTableIdx = ui128IpHash[14] * ui128IpHash[15];
        } else {
            bIPv6 = true;
#ifdef _WIN32
            win_inet_ntop(&((struct sockaddr_in6 *)&AccptSocket->addr)->sin6_addr, sIP, 46);
#else
            inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&AccptSocket->addr)->sin6_addr, sIP, 46);
#endif
            ui16IpTableIdx = GetIpTableIdx(ui128IpHash);
        }
    } else {
        strcpy(sIP, inet_ntoa(((struct sockaddr_in *)&AccptSocket->addr)->sin_addr));

        ui128IpHash[10] = 255;
        ui128IpHash[11] = 255;
        memcpy(ui128IpHash+12, &((struct sockaddr_in *)&AccptSocket->addr)->sin_addr.s_addr, 4);

        ui16IpTableIdx = ui128IpHash[14] * ui128IpHash[15];
    }

    // set the recv buffer
#ifdef _WIN32
    int32_t bufsize = 8192;
    if(setsockopt(AccptSocket->s, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize, sizeof(bufsize)) == SOCKET_ERROR) {
    	int iError = WSAGetLastError();
    	int imsgLen = sprintf(msg, "[SYS] setsockopt failed on attempt to set SO_RCVBUF. IP: %s Err: %s (%d)",  sIP, WSErrorStr(iError), iError);
#else
    int bufsize = 8192;
    if(setsockopt(AccptSocket->s, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == -1) {
    	int imsgLen = sprintf(msg, "[SYS] setsockopt failed on attempt to set SO_RCVBUF. IP: %s Err: %d", sIP, errno);
#endif
        if(CheckSprintf(imsgLen, 1024, "theLoop::AcceptUser1") == true) {
    	   UdpDebug->Broadcast(msg, imsgLen);
        }
#ifdef _WIN32
    	shutdown(AccptSocket->s, SD_SEND);
        closesocket(AccptSocket->s);
#else
    	shutdown(AccptSocket->s, SHUT_RDWR);
        close(AccptSocket->s);
#endif
        return;
    }

    // set the send buffer
    bufsize = 32768;
#ifdef _WIN32
    if(setsockopt(AccptSocket->s, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize, sizeof(bufsize)) == SOCKET_ERROR) {
        int iError = WSAGetLastError();
        int imsgLen = sprintf(msg, "[SYS] setsockopt failed on attempt to set SO_SNDBUF. IP: %s Err: %s (%d)", sIP, WSErrorStr(iError), iError);
#else
    if(setsockopt(AccptSocket->s, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == -1) {
        int imsgLen = sprintf(msg, "[SYS] setsockopt failed on attempt to set SO_SNDBUF. IP: %s Err: %d", sIP, errno);
#endif
        if(CheckSprintf(imsgLen, 1024, "theLoop::AcceptUser2") == true) {
	       UdpDebug->Broadcast(msg, imsgLen);
        }
#ifdef _WIN32
	    shutdown(AccptSocket->s, SD_SEND);
        closesocket(AccptSocket->s);
#else
	    shutdown(AccptSocket->s, SHUT_RDWR);
        close(AccptSocket->s);
#endif
        return;
    }

    // set sending of keepalive packets
#ifdef _WIN32
    bool bKeepalive = true;
    setsockopt(AccptSocket->s, SOL_SOCKET, SO_KEEPALIVE, (char *)&bKeepalive, sizeof(bKeepalive));
#else
    int iKeepAlive = 1;
    if(setsockopt(AccptSocket->s, SOL_SOCKET, SO_KEEPALIVE, &iKeepAlive, sizeof(iKeepAlive)) == -1) {
        int imsgLen = sprintf(msg, "[SYS] setsockopt failed on attempt to set SO_KEEPALIVE. IP: %s Err: %d", sIP, errno);
        if(CheckSprintf(imsgLen, 1024, "theLoop::AcceptUser3") == true) {
	       UdpDebug->Broadcast(msg, imsgLen);
        }
	    shutdown(AccptSocket->s, SHUT_RDWR);
        close(AccptSocket->s);
        return;
    }
#endif

    // set non-blocking mode
#ifdef _WIN32
    uint32_t block = 1;
	if(ioctlsocket(AccptSocket->s, FIONBIO, (unsigned long *)&block) == SOCKET_ERROR) {
    	int iError = WSAGetLastError();
    	int imsgLen = sprintf(msg, "[SYS] ioctlsocket failed on attempt to set FIONBIO. IP: %s Err: %s (%d)", sIP, WSErrorStr(iError), iError);
#else
    int oldFlag = fcntl(AccptSocket->s, F_GETFL, 0);
    if(fcntl(AccptSocket->s, F_SETFL, oldFlag | O_NONBLOCK) == -1) {
    	int imsgLen = sprintf(msg, "[SYS] fcntl failed on attempt to set O_NONBLOCK. IP: %s Err: %d", sIP, errno);
#endif
        if(CheckSprintf(imsgLen, 1024, "theLoop::AcceptUser3") == true) {
		  UdpDebug->Broadcast(msg, imsgLen);
		}
#ifdef _WIN32
		shutdown(AccptSocket->s, SD_SEND);
		closesocket(AccptSocket->s);
#else
		shutdown(AccptSocket->s, SHUT_RDWR);
		close(AccptSocket->s);
#endif
		return;
    }
    
    if(SettingManager->bBools[SETBOOL_REDIRECT_ALL] == true) {
        if(SettingManager->sPreTexts[SetMan::SETPRETXT_REDIRECT_ADDRESS] != NULL) {
       	    int imsgLen = sprintf(msg, "<%s> %s %s|%s", SettingManager->sPreTexts[SetMan::SETPRETXT_HUB_SEC], LanguageManager->sTexts[LAN_YOU_REDIR_TO],
               SettingManager->sTexts[SETTXT_REDIRECT_ADDRESS], SettingManager->sPreTexts[SetMan::SETPRETXT_REDIRECT_ADDRESS]);
            if(CheckSprintf(imsgLen, 1024, "theLoop::AcceptUser4") == true) {
                send(AccptSocket->s, msg, imsgLen, 0);
                ui64BytesSent += imsgLen;
            }
        }
#ifdef _WIN32
        shutdown(AccptSocket->s, SD_SEND);
        closesocket(AccptSocket->s);
#else
        shutdown(AccptSocket->s, SHUT_RDWR);
        close(AccptSocket->s);
#endif
		return;
    }

    time_t acc_time;
    time(&acc_time);

	BanItem * Ban = hashBanManager->FindFull(ui128IpHash, acc_time);

	if(Ban != NULL) {
        if(((Ban->ui8Bits & hashBanMan::FULL) == hashBanMan::FULL) == true) {
            int imsglen;
            char *messg = GenerateBanMessage(Ban, imsglen, acc_time);
            send(AccptSocket->s, messg, imsglen, 0);
#ifdef _WIN32
            shutdown(AccptSocket->s, SD_SEND);
            closesocket(AccptSocket->s);
#else
            shutdown(AccptSocket->s, SHUT_RD);
            close(AccptSocket->s);
#endif
/*            int imsgLen = sprintf(msg, "[SYS] Banned ip %s - connection closed.", sIP);
            if(CheckSprintf(imsgLen, 1024, "theLoop::AcceptUser5") == true) {
                UdpDebug->Broadcast(msg, imsgLen);
            }*/
            return;
        }
    }

	RangeBanItem * RangeBan = hashBanManager->FindFullRange(ui128IpHash, acc_time);

	if(RangeBan != NULL) {
        if(((RangeBan->ui8Bits & hashBanMan::FULL) == hashBanMan::FULL) == true) {
            int imsglen;
            char *messg = GenerateRangeBanMessage(RangeBan, imsglen, acc_time);
            send(AccptSocket->s, messg, imsglen, 0);
#ifdef _WIN32
            shutdown(AccptSocket->s, SD_SEND);
            closesocket(AccptSocket->s);
#else
            shutdown(AccptSocket->s, SHUT_RD);
            close(AccptSocket->s);
#endif
/*            int imsgLen = sprintf(msg, "[SYS] Range Banned ip %s - connection closed.", sIP);
            if(CheckSprintf(imsgLen, 1024, "theLoop::AcceptUser6") == true) {
                UdpDebug->Broadcast(msg, imsgLen);
            }*/
            return;
        }
    }

    ui32Joins++;

    // set properties of the new user object
	User * pUser = new User();

	if(pUser == NULL) {
#ifdef _WIN32
		shutdown(AccptSocket->s, SD_SEND);
		closesocket(AccptSocket->s);
#else
		shutdown(AccptSocket->s, SHUT_RDWR);
		close(AccptSocket->s);
#endif
        AppendDebugLog("%s - [MEM] Cannot allocate pUser in theLoop::AcceptUser\n", 0);
		return;
	}

	pUser->uLogInOut = new LoginLogout();

    if(pUser->uLogInOut == NULL) {
#ifdef _WIN32
		shutdown(AccptSocket->s, SD_SEND);
		closesocket(AccptSocket->s);
#else
		shutdown(AccptSocket->s, SHUT_RDWR);
		close(AccptSocket->s);
#endif
        delete pUser;

        AppendDebugLog("%s - [MEM] Cannot allocate uLogInOut in theLoop::AcceptUser\n", 0);
		return;
    }

    pUser->uLogInOut->logonClk = ui64ActualTick;
    pUser->Sck = AccptSocket->s;
    pUser->ui8State = User::STATE_KEY_OR_SUP;

    memcpy(pUser->ui128IpHash, ui128IpHash, 16);
    pUser->ui16IpTableIdx = ui16IpTableIdx;

    UserSetIP(pUser, sIP);

    if(bIPv6 == true) {
        pUser->ui32BoolBits |= User::BIT_IPV6;
    } else {
        pUser->ui32BoolBits |= User::BIT_IPV4;
    }

    if(UserMakeLock(pUser) == false) {
#ifdef _WIN32
		shutdown(AccptSocket->s, SD_SEND);
		closesocket(AccptSocket->s);
#else
		shutdown(AccptSocket->s, SHUT_RDWR);
		close(AccptSocket->s);
#endif
        delete pUser;
        return;
    }
    
    if(Ban != NULL) {
        uint32_t hash = 0;
        if(((Ban->ui8Bits & hashBanMan::NICK) == hashBanMan::NICK) == true) {
            hash = Ban->ui32NickHash;
        }
        int imsglen;
        char *messg = GenerateBanMessage(Ban, imsglen, acc_time);
        pUser->uLogInOut->uBan = new UserBan(messg, imsglen, hash);
        if(pUser->uLogInOut->uBan == NULL || pUser->uLogInOut->uBan->sMessage == NULL) {
#ifdef _WIN32
            shutdown(AccptSocket->s, SD_SEND);
            closesocket(AccptSocket->s);
#else
            shutdown(AccptSocket->s, SHUT_RDWR);
            close(AccptSocket->s);
#endif
            if(pUser->uLogInOut->uBan == NULL) {
                AppendDebugLog("%s - [MEM] Cannot allocate new uBan in theLoop::AcceptUser\n", 0);
            } else {
                AppendDebugLog("%s - [MEM] Cannot allocate uBan->sMessage in theLoop::AcceptUser\n", 0);
            }

            delete pUser;

            return;
        }
    } else if(RangeBan != NULL) {
        int imsglen;
        char *messg = GenerateRangeBanMessage(RangeBan, imsglen, acc_time);
        pUser->uLogInOut->uBan = new UserBan(messg, imsglen, 0);
        if(pUser->uLogInOut->uBan == NULL || pUser->uLogInOut->uBan->sMessage == NULL) {
#ifdef _WIN32
            shutdown(AccptSocket->s, SD_SEND);
            closesocket(AccptSocket->s);
#else
            shutdown(AccptSocket->s, SHUT_RDWR);
            close(AccptSocket->s);
#endif
            if(pUser->uLogInOut->uBan == NULL) {
        	   AppendDebugLog("%s - [MEM] Cannot allocate new uBan in theLoop::AcceptUser1\n", 0);
            } else {
                AppendDebugLog("%s - [MEM] Cannot allocate uBan->sMessage in theLoop::AcceptUser1\n", 0);
            }

            delete pUser;

        	return;
        }
    }
        
    // Everything is ok, now add to users...
    colUsers->AddUser(pUser);
}
//---------------------------------------------------------------------------

void theLoop::ReceiveLoop() {
#ifndef _WIN32
    while((iSIG = sigtimedwait(&sst, &info, &zerotime)) != -1) {
        if(iSIG == SIGSCRTMR) {
            ScriptOnTimer((ScriptTimer *)info.si_value.sival_ptr);
        } else if(iSIG == SIGREGTMR) {
            RegTimerHandler();
        }
    }
#endif

    // Receiving loop for process all incoming data and store in queues
    uint32_t iRecvRests = 0;
    
    ui8SrCntr++;
    
    if(ui8SrCntr >= 7 || (colUsers->ui16ActSearchs + colUsers->ui16PasSearchs) > 8 || 
        colUsers->ui16ActSearchs > 5) {
        ui8SrCntr = 0;
    }

    if(ui64ActualTick-iLstUptmTck > 60) {
        time_t acctime;
        time(&acctime);
        acctime -= starttime;
    
        uint64_t iValue = acctime / 86400;
		acctime -= (time_t)(86400*iValue);
        iDays = iValue;
    
        iValue = acctime / 3600;
    	acctime -= (time_t)(3600*iValue);
        iHours = iValue;
    
    	iValue = acctime / 60;
        iMins = iValue;

#ifdef _WIN32
        if(iMins == 0 || iMins == 15 || iMins == 30 || iMins == 45) {
            if(HeapValidate(GetProcessHeap(), 0, 0) == 0) {
                AppendDebugLog("%s - [ERR] Process memory heap corrupted\n", 0);
            }
            HeapCompact(GetProcessHeap(), 0);

            if(HeapValidate(hPtokaXHeap, HEAP_NO_SERIALIZE, 0) == 0) {
                AppendDebugLog("%s - [ERR] PtokaX memory heap corrupted\n", 0);
            }
            HeapCompact(hPtokaXHeap, HEAP_NO_SERIALIZE);

            if(HeapValidate(hRecvHeap, HEAP_NO_SERIALIZE, 0) == 0) {
                AppendDebugLog("%s - [ERR] Recv memory heap corrupted\n", 0);
            }
            HeapCompact(hRecvHeap, HEAP_NO_SERIALIZE);

            if(HeapValidate(hSendHeap, HEAP_NO_SERIALIZE, 0) == 0) {
                AppendDebugLog("%s - [ERR] Send memory heap corrupted\n", 0);
            }
            HeapCompact(hSendHeap, HEAP_NO_SERIALIZE);

            if(HeapValidate(hLuaHeap, 0, 0) == 0) {
                AppendDebugLog("%s - [ERR] Lua memory heap corrupted\n", 0);
            }
            HeapCompact(hLuaHeap, 0);
        }
#endif

        iLstUptmTck = ui64ActualTick;
    }

    AcceptedSocket *NextSck = NULL;

#ifdef _WIN32
    EnterCriticalSection(&csAcceptQueue);
#else
	pthread_mutex_lock(&mtxAcceptQueue);
#endif

    if(AcceptedSocketsS != NULL) {
        NextSck = AcceptedSocketsS;
        AcceptedSocketsS = NULL;
        AcceptedSocketsE = NULL;
    }

#ifdef _WIN32
    LeaveCriticalSection(&csAcceptQueue);
#else
	pthread_mutex_unlock(&mtxAcceptQueue);
#endif

    while(NextSck != NULL) {
        AcceptedSocket *CurSck = NextSck;
        NextSck = CurSck->next;
        AcceptUser(CurSck);
        delete CurSck;
    }

    User *nextUser = colUsers->llist;
    while(nextUser != 0 && bServerTerminated == false) {
        User *curUser = nextUser;
        nextUser = curUser->next;

        // PPK ... true == we have rest ;)
        if(UserDoRecv(curUser) == true) {
            iRecvRests++;
            //Memo("Rest " + string(curUser->Nick, curUser->NickLen) + ": '" + string(curUser->recvbuf) + "'");
        }

        //    curUser->ProcessLines();
        //}

        switch(curUser->ui8State) {
            case User::STATE_KEY_OR_SUP:{
                // check logon timeout for iState 1
                if(ui64ActualTick - curUser->uLogInOut->logonClk > 20) {
                    int imsgLen = sprintf(msg, "[SYS] Login timeout 1 for %s - user disconnected.", curUser->sIP);
                    if(CheckSprintf(imsgLen, 1024, "theLoop::ReceiveLoop3") == true) {
                        UdpDebug->Broadcast(msg, imsgLen);
                    }
                    UserClose(curUser);
                    continue;
                }
                break;
            }
            case User::STATE_IPV4_CHECK: {
                // check IPv4Check timeout
                if((ui64ActualTick - curUser->uLogInOut->ui64IPv4CheckTick) > 10) {
                    int imsgLen = sprintf(msg, "[SYS] IPv4Check timeout for %s (%s).", curUser->sNick, curUser->sIP);
                    if(CheckSprintf(imsgLen, 1024, "theLoop::ReceiveLoop31") == true) {
                        UdpDebug->Broadcast(msg, imsgLen);
                    }
                    curUser->ui8State = User::STATE_ADDME;
                    continue;
                }
                break;
            }
            case User::STATE_ADDME: {
                // PPK ... Add user, but only if send $GetNickList (or have quicklist supports) <- important, used by flooders !!!
                if(((curUser->ui32BoolBits & User::BIT_GETNICKLIST) == User::BIT_GETNICKLIST) == false &&
                    ((curUser->ui32SupportBits & User::SUPPORTBIT_QUICKLIST) == User::SUPPORTBIT_QUICKLIST) == false &&
                    ((curUser->ui32BoolBits & User::BIT_PINGER) == User::BIT_PINGER) == true)
                    continue;

                int imsgLen = GetWlcmMsg(msg);
                UserSendCharDelayed(curUser, msg, imsgLen);
                curUser->ui8State = User::STATE_ADDME_1LOOP;
                continue;
            }
            case User::STATE_ADDME_1LOOP: {
                // PPK ... added login delay.
                if(dLoggedUsers >= dActualSrvLoopLogins && ((curUser->ui32BoolBits & User::BIT_OPERATOR) == User::BIT_OPERATOR) == false) {
                    if(ui64ActualTick - curUser->uLogInOut->logonClk > 300) {
                        int imsgLen = sprintf(msg, "[SYS] Login timeout (%d) 3 for %s (%s) - user disconnected.", (int)curUser->ui8State, curUser->sNick, curUser->sIP);
                        if(CheckSprintf(imsgLen, 1024, "theLoop::ReceiveLoop4") == true) {
                            UdpDebug->Broadcast(msg, imsgLen);
                        }
                        UserClose(curUser);
                    }
                    continue;
                }

                // PPK ... is not more needed, free mem ;)
                if(curUser->uLogInOut->pBuffer != NULL) {
#ifdef _WIN32
                    if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curUser->uLogInOut->pBuffer) == 0) {
						AppendDebugLog("%s - [MEM] Cannot deallocate curUser->uLogInOut->pBuffer in theLoop::ReceiveLoop\n", 0);
                    }
#else
					free(curUser->uLogInOut->pBuffer);
#endif
                    curUser->uLogInOut->pBuffer = NULL;
                }

                if((curUser->ui32BoolBits & User::BIT_IPV6) == User::BIT_IPV6 && ((curUser->ui32BoolBits & User::SUPPORTBIT_IPV4) == User::SUPPORTBIT_IPV4) == false) {
                    in_addr ipv4addr;
					ipv4addr.s_addr = INADDR_NONE;

                    if(curUser->ui128IpHash[0] == 32 && curUser->ui128IpHash[1] == 2) { // 6to4 tunnel
                        memcpy(&ipv4addr, curUser->ui128IpHash + 2, 4);
                    } else if(curUser->ui128IpHash[0] == 32 && curUser->ui128IpHash[1] == 1 && curUser->ui128IpHash[2] == 0 && curUser->ui128IpHash[3] == 0) { // teredo tunnel
                        uint32_t ui32Ip = 0;
                        memcpy(&ui32Ip, curUser->ui128IpHash + 12, 4);
                        ui32Ip ^= 0xffffffff;
                        memcpy(&ipv4addr, &ui32Ip, 4);
                    }

                    if(ipv4addr.s_addr != INADDR_NONE) {
                        strcpy(curUser->sIPv4, inet_ntoa(ipv4addr));
                        curUser->ui8IPv4Len = (uint8_t)strlen(curUser->sIPv4);
                        curUser->ui32BoolBits |= User::BIT_IPV4;
                    }
                }

                //New User Connected ... the user is operator ? invoke lua User/OpConnected
                uint32_t iBeforeLuaLen = curUser->sbdatalen;

				bool bRet = ScriptManager->UserConnected(curUser);
				if(curUser->ui8State >= User::STATE_CLOSING) {// connection closed by script?
                    if(bRet == false) { // only when all scripts process userconnected
                        ScriptManager->UserDisconnected(curUser);
                    }

					continue;
				}

                if(iBeforeLuaLen < curUser->sbdatalen) {
                    size_t szNeededLen = curUser->sbdatalen-iBeforeLuaLen;

					void * sOldBuf = curUser->uLogInOut->pBuffer;
#ifdef _WIN32
					if(curUser->uLogInOut->pBuffer == NULL) {
						curUser->uLogInOut->pBuffer = (char *)HeapAlloc(hPtokaXHeap, HEAP_NO_SERIALIZE, szNeededLen+1);
					} else {
						curUser->uLogInOut->pBuffer = (char *)HeapReAlloc(hPtokaXHeap, HEAP_NO_SERIALIZE, sOldBuf, szNeededLen+1);
					}
#else
					curUser->uLogInOut->pBuffer = (char *)realloc(sOldBuf, szNeededLen+1);
#endif
                    if(curUser->uLogInOut->pBuffer == NULL) {
                        curUser->ui32BoolBits |= User::BIT_ERROR;
                        UserClose(curUser);

						AppendDebugLog("%s - [MEM] Cannot allocate %" PRIu64 " bytes for sLockUsrConn in theLoop::ReceiveLoop\n", (uint64_t)(szNeededLen+1));

                		continue;
                    }
                    memcpy(curUser->uLogInOut->pBuffer, curUser->sendbuf+iBeforeLuaLen, szNeededLen);
                	curUser->uLogInOut->iUserConnectedLen = (uint32_t)szNeededLen;
                	curUser->uLogInOut->pBuffer[curUser->uLogInOut->iUserConnectedLen] = '\0';
                	curUser->sbdatalen = iBeforeLuaLen;
                	curUser->sendbuf[curUser->sbdatalen] = '\0';
                }

                // PPK ... wow user is accepted, now add it :)
                if(((curUser->ui32BoolBits & User::BIT_HAVE_BADTAG) == User::BIT_HAVE_BADTAG) == true) {
                    UserHasSuspiciousTag(curUser);
                }
                    
                UserAdd2Userlist(curUser);
                
                dLoggedUsers++;
                curUser->ui8State = User::STATE_ADDME_2LOOP;
                ui64TotalShare += curUser->ui64SharedSize;
                curUser->ui32BoolBits |= User::BIT_HAVE_SHARECOUNTED;
                
#ifdef _BUILD_GUI
                if(::SendMessage(pMainWindowPageUsersChat->hWndPageItems[MainWindowPageUsersChat::BTN_AUTO_UPDATE_USERLIST], BM_GETCHECK, 0, 0) == BST_CHECKED) {
                    pMainWindowPageUsersChat->AddUser(curUser);
                }
#endif
//                if(sqldb) sqldb->AddVisit(curUser);

                // PPK ... change to NoHello supports
            	int imsgLen = sprintf(msg, "$Hello %s|", curUser->sNick);
            	if(CheckSprintf(imsgLen, 1024, "theLoop::ReceiveLoop6") == true) {
                    g_GlobalDataQueue->AddQueueItem(msg, imsgLen, NULL, 0, GlobalDataQueue::CMD_HELLO);
                }

                g_GlobalDataQueue->UserIPStore(curUser);

                switch(SettingManager->ui8FullMyINFOOption) {
                    case 0:
                        g_GlobalDataQueue->AddQueueItem(curUser->sMyInfoLong, curUser->ui16MyInfoLongLen, NULL, 0, GlobalDataQueue::CMD_MYINFO);
                        break;
                    case 1:
                        g_GlobalDataQueue->AddQueueItem(curUser->sMyInfoShort, curUser->ui16MyInfoShortLen, curUser->sMyInfoLong, curUser->ui16MyInfoLongLen, GlobalDataQueue::CMD_MYINFO);
                        break;
                    case 2:
                        g_GlobalDataQueue->AddQueueItem(curUser->sMyInfoShort, curUser->ui16MyInfoShortLen, NULL, 0, GlobalDataQueue::CMD_MYINFO);
                        break;
                    default:
                        break;
                }
                
                if(((curUser->ui32BoolBits & User::BIT_OPERATOR) == User::BIT_OPERATOR) == true) {
                    g_GlobalDataQueue->OpListStore(curUser->sNick);
                }
                
                curUser->iLastMyINFOSendTick = ui64ActualTick;
                break;
            }
            case User::STATE_ADDED:
                if(curUser->cmdToUserStrt != NULL) {
                    PrcsdToUsrCmd *next = curUser->cmdToUserStrt;
                        
                    curUser->cmdToUserStrt = NULL;
                    curUser->cmdToUserEnd = NULL;
            
                    while(next != NULL) {
                        PrcsdToUsrCmd *cur = next;
                        next = cur->next;
                                               
                        if(cur->iLoops >= 2) {
                            User * ToUser = hashManager->FindUser(cur->ToNick, cur->iToNickLen);
                            if(ToUser == cur->To) {
                                if(SettingManager->iShorts[SETSHORT_MAX_PM_COUNT_TO_USER] == 0 || cur->iPmCount == 0) {
                                    UserSendCharDelayed(cur->To, cur->sCommand, cur->iLen);
                                } else {
                                    if(cur->To->iReceivedPmCount == 0) {
                                        cur->To->iReceivedPmTick = ui64ActualTick;
                                    } else if(cur->To->iReceivedPmCount >= (uint32_t)SettingManager->iShorts[SETSHORT_MAX_PM_COUNT_TO_USER]) {
                                        if(cur->To->iReceivedPmTick+60 < ui64ActualTick) {
                                            cur->To->iReceivedPmTick = ui64ActualTick;
                                            cur->To->iReceivedPmCount = 0;
                                        } else {
                                            bool bSprintfCheck;
                                            int imsgLen;
                                            if(cur->iPmCount == 1) {
                                                imsgLen = sprintf(msg, "$To: %s From: %s $<%s> %s %s %s!|", curUser->sNick, cur->ToNick, SettingManager->sPreTexts[SetMan::SETPRETXT_HUB_SEC],
                                                    LanguageManager->sTexts[LAN_SRY_LST_MSG_BCS], cur->ToNick, LanguageManager->sTexts[LAN_EXC_MSG_LIMIT]);
                                                bSprintfCheck = CheckSprintf(imsgLen, 1024, "theLoop::ReceiveLoop1");
                                            } else {
                                                imsgLen = sprintf(msg, "$To: %s From: %s $<%s> %s %d %s %s %s!|", curUser->sNick, cur->ToNick,
                                                    SettingManager->sPreTexts[SetMan::SETPRETXT_HUB_SEC], LanguageManager->sTexts[LAN_SORRY_LAST], cur->iPmCount,
                                                    LanguageManager->sTexts[LAN_MSGS_NOT_SENT], cur->ToNick, LanguageManager->sTexts[LAN_EXC_MSG_LIMIT]);
                                                bSprintfCheck = CheckSprintf(imsgLen, 1024, "theLoop::ReceiveLoop2");
                                            }
                                            if(bSprintfCheck == true) {
                                                UserSendCharDelayed(curUser, msg, imsgLen);
                                            }

#ifdef _WIN32
                                            if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)cur->sCommand) == 0) {
												AppendDebugLog("%s - [MEM] Cannot deallocate cur->sCommand in theLoop::ReceiveLoop\n", 0);
                                            }
#else
											free(cur->sCommand);
#endif
                                            cur->sCommand = NULL;

#ifdef _WIN32
                                            if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)cur->ToNick) == 0) {
												AppendDebugLog("%s - [MEM] Cannot deallocate cur->ToNick in theLoop::ReceiveLoop\n", 0);
                                            }
#else
											free(cur->ToNick);
#endif
                                            cur->ToNick = NULL;
        
                                            delete cur;

                                            continue;
                                        }
                                    }  
                                    UserSendCharDelayed(cur->To, cur->sCommand, cur->iLen);
                                    cur->To->iReceivedPmCount += cur->iPmCount;
                                }
                            }
                        } else {
                            cur->iLoops++;
                            if(curUser->cmdToUserStrt == NULL) {
                                cur->next = NULL;
                                curUser->cmdToUserStrt = cur;
                                curUser->cmdToUserEnd = cur;
                            } else {
                                curUser->cmdToUserEnd->next = cur;
                                curUser->cmdToUserEnd = cur;
                            }
                            continue;
                        }

#ifdef _WIN32
                        if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)cur->sCommand) == 0) {
							AppendDebugLog("%s - [MEM] Cannot deallocate cur->sCommand1 in theLoop::ReceiveLoop\n", 0);
                        }
#else
						free(cur->sCommand);
#endif
                        cur->sCommand = NULL;

#ifdef _WIN32
                        if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)cur->ToNick) == 0) {
							AppendDebugLog("%s - [MEM] Cannot deallocate cur->ToNick1 in theLoop::ReceiveLoop\n", 0);
                        }
#else
						free(cur->ToNick);
#endif
                        cur->ToNick = NULL;
        
                        delete cur;
					}
                }
        
                if(ui8SrCntr == 0) {
                    if(curUser->cmdActive6Search != NULL) {
						if(curUser->cmdActive4Search != NULL) {
							g_GlobalDataQueue->AddQueueItem(curUser->cmdActive6Search->sCommand, curUser->cmdActive6Search->iLen, 
								curUser->cmdActive4Search->sCommand, curUser->cmdActive4Search->iLen, GlobalDataQueue::CMD_ACTIVE_SEARCH_V64);
						} else {
							g_GlobalDataQueue->AddQueueItem(curUser->cmdActive6Search->sCommand, curUser->cmdActive6Search->iLen, NULL, 0, GlobalDataQueue::CMD_ACTIVE_SEARCH_V6);
						}
                    } else if(curUser->cmdActive4Search != NULL) {
						g_GlobalDataQueue->AddQueueItem(curUser->cmdActive4Search->sCommand, curUser->cmdActive4Search->iLen, NULL, 0, GlobalDataQueue::CMD_ACTIVE_SEARCH_V4);
					}

                    if(curUser->cmdPassiveSearch != NULL) {
						uint8_t ui8CmdType = GlobalDataQueue::CMD_PASSIVE_SEARCH_V4;
						if((curUser->ui32BoolBits & User::BIT_IPV6) == User::BIT_IPV6) {
							if((curUser->ui32BoolBits & User::BIT_IPV4) == User::BIT_IPV4) {
                                if((curUser->ui32BoolBits & User::BIT_IPV6_ACTIVE) == User::BIT_IPV6_ACTIVE) {
                                    ui8CmdType = GlobalDataQueue::CMD_PASSIVE_SEARCH_V4_ONLY;
                                } else if((curUser->ui32BoolBits & User::BIT_IPV4_ACTIVE) == User::BIT_IPV4_ACTIVE) {
                                    ui8CmdType = GlobalDataQueue::CMD_PASSIVE_SEARCH_V6_ONLY;
                                } else {
                                    ui8CmdType = GlobalDataQueue::CMD_PASSIVE_SEARCH_V64;
                                }
                            } else {
								ui8CmdType = GlobalDataQueue::CMD_PASSIVE_SEARCH_V6;
                            }
						}

						g_GlobalDataQueue->AddQueueItem(curUser->cmdPassiveSearch->sCommand, curUser->cmdPassiveSearch->iLen, NULL, 0, ui8CmdType);

                        UserDeletePrcsdUsrCmd(curUser->cmdPassiveSearch);
                        curUser->cmdPassiveSearch = NULL;
                    }
                }

                // PPK ... deflood memory cleanup, if is not needed anymore
				if(ui8SrCntr == 0) {
					if(curUser->sLastChat != NULL && curUser->ui16LastChatLines < 2 && 
                        (curUser->ui64SameChatsTick+SettingManager->iShorts[SETSHORT_SAME_MAIN_CHAT_TIME]) < ui64ActualTick) {
#ifdef _WIN32
                        if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curUser->sLastChat) == 0) {
                            AppendDebugLog("%s - [MEM] Cannot deallocate curUser->sLastChat in theLoop::ReceiveLoop\n", 0);
                        }
#else
						free(curUser->sLastChat);
#endif
                        curUser->sLastChat = NULL;
						curUser->ui16LastChatLen = 0;
						curUser->ui16SameMultiChats = 0;
						curUser->ui16LastChatLines = 0;
                    }

					if(curUser->sLastPM != NULL && curUser->ui16LastPmLines < 2 && 
                        (curUser->ui64SamePMsTick+SettingManager->iShorts[SETSHORT_SAME_PM_TIME]) < ui64ActualTick) {
#ifdef _WIN32
						if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curUser->sLastPM) == 0) {
							AppendDebugLog("%s - [MEM] Cannot deallocate curUser->sLastPM in theLoop::ReceiveLoop\n", 0);
                        }
#else
						free(curUser->sLastPM);
#endif
                        curUser->sLastPM = NULL;
                        curUser->ui16LastPMLen = 0;
						curUser->ui16SameMultiPms = 0;
                        curUser->ui16LastPmLines = 0;
                    }
                    
					if(curUser->sLastSearch != NULL && (curUser->ui64SameSearchsTick+SettingManager->iShorts[SETSHORT_SAME_SEARCH_TIME]) < ui64ActualTick) {
#ifdef _WIN32
                        if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curUser->sLastSearch) == 0) {
							AppendDebugLog("%s - [MEM] Cannot deallocate curUser->sLastSearch in theLoop::ReceiveLoop\n", 0);
                        }
#else
						free(curUser->sLastSearch);
#endif
                        curUser->sLastSearch = NULL;
                        curUser->ui16LastSearchLen = 0;
                    }
                }
                continue;
            case User::STATE_CLOSING: {
                if(((curUser->ui32BoolBits & User::BIT_ERROR) == User::BIT_ERROR) == false && curUser->sbdatalen != 0) {
                  	if(curUser->uLogInOut->iToCloseLoops != 0 || ((curUser->ui32BoolBits & User::BIT_PINGER) == User::BIT_PINGER) == true) {
                		UserTry2Send(curUser);
                		curUser->uLogInOut->iToCloseLoops--;
                		continue;
                	}
                }
            	curUser->ui8State = User::STATE_REMME;
            	continue;
            }
            // if user is marked as dead, remove him
            case User::STATE_REMME: {
#ifdef _WIN32
                shutdown(curUser->Sck, SD_SEND);
                closesocket(curUser->Sck);
#else
                shutdown(curUser->Sck, SHUT_RD);
                close(curUser->Sck);
#endif

                // linked list
                colUsers->RemUser(curUser);

                delete curUser;
                continue;
            }
            default: {
                // check logon timeout
                if(ui64ActualTick - curUser->uLogInOut->logonClk > 60) {
                    int imsgLen = sprintf(msg, "[SYS] Login timeout (%d) 2 for %s (%s) - user disconnected.", (int)curUser->ui8State, curUser->sNick, curUser->sIP);
                    if(CheckSprintf(imsgLen, 1024, "theLoop::ReceiveLoop7") == true) {
                        UdpDebug->Broadcast(msg, imsgLen);
                    }
                    UserClose(curUser);
                    continue;
                }
                break;
            }
        }
    }
    
    if(ui8SrCntr == 0) {
        colUsers->ui16ActSearchs = 0;
        colUsers->ui16PasSearchs = 0;
    }

    iLastRecvRest = iRecvRests;
    iRecvRestsPeak = iRecvRests > iRecvRestsPeak ? iRecvRests : iRecvRestsPeak;
}
//---------------------------------------------------------------------------

void theLoop::SendLoop() {
    g_GlobalDataQueue->PrepareQueueItems();

    // PPK ... send loop
    // now logging users get changed myinfo with myinfos
    // old users get it in this loop from queue -> badwith saving !!! no more twice myinfo =)
    // Sending Loop
    uint32_t iSendRests = 0;

    User *nextUser = colUsers->llist;
    while(nextUser != 0 && bServerTerminated == false) {
        User *curUser = nextUser;
        nextUser = curUser->next;

        switch(curUser->ui8State) {
            case User::STATE_ADDME_2LOOP: {
                ui32Logged++;

                if(ui32Peak < ui32Logged) {
                    ui32Peak = ui32Logged;
                    if(SettingManager->iShorts[SETSHORT_MAX_USERS_PEAK] < (int16_t)ui32Peak)
                        SettingManager->SetShort(SETSHORT_MAX_USERS_PEAK, (int16_t)ui32Peak);
                }

            	curUser->ui8State = User::STATE_ADDED;

            	// finaly send the nicklist/myinfos/oplist
                UserAddUserList(curUser);
                
                // PPK ... UserIP2 supports
                if(((curUser->ui32SupportBits & User::SUPPORTBIT_USERIP2) == User::SUPPORTBIT_USERIP2) == true &&
                    ((curUser->ui32BoolBits & User::BIT_QUACK_SUPPORTS) == User::BIT_QUACK_SUPPORTS) == false &&
                    ProfileMan->IsAllowed(curUser, ProfileManager::SENDALLUSERIP) == false) {
            		int imsgLen = sprintf(msg, "$UserIP %s %s|", curUser->sNick, (curUser->sIPv4[0] == '\0' ? curUser->sIP : curUser->sIPv4));
            		if(CheckSprintf(imsgLen, 1024, "theLoop::SendLoop1") == true) {
                        UserSendCharDelayed(curUser, msg, imsgLen);
                    }
                }
                
                curUser->ui32BoolBits &= ~User::BIT_GETNICKLIST;

                // PPK ... send motd ???
                if(SettingManager->ui16PreTextsLens[SetMan::SETPRETXT_MOTD] != 0) {
                    if(SettingManager->bBools[SETBOOL_MOTD_AS_PM] == true) {
                        int imsgLen = sprintf(g_sBuffer, SettingManager->sPreTexts[SetMan::SETPRETXT_MOTD], curUser->sNick);
                        if(CheckSprintf(imsgLen, g_szBufferSize, "theLoop::SendLoop2") == true) {
                            UserSendCharDelayed(curUser, g_sBuffer, imsgLen);
                        }
                    } else {
                        UserSendCharDelayed(curUser, SettingManager->sPreTexts[SetMan::SETPRETXT_MOTD],
                            SettingManager->ui16PreTextsLens[SetMan::SETPRETXT_MOTD]);
                    }
                }

                // check for Debug subscription
                if(((curUser->ui32BoolBits & User::BIT_OPERATOR) == User::BIT_OPERATOR) == true)
                    UdpDebug->CheckUdpSub(curUser, true);

                if(curUser->uLogInOut->iUserConnectedLen != 0) {
                    UserPutInSendBuf(curUser, curUser->uLogInOut->pBuffer, curUser->uLogInOut->iUserConnectedLen);
#ifdef _WIN32
                    if(HeapFree(hPtokaXHeap, HEAP_NO_SERIALIZE, (void *)curUser->uLogInOut->pBuffer) == 0) {
						AppendDebugLog("%s - [MEM] Cannot deallocate curUser->uLogInOut->pBuffer in theLoop::SendLoop\n", 0);
                    }
#else
					free(curUser->uLogInOut->pBuffer);
#endif

                    curUser->uLogInOut->pBuffer = NULL;
                }

                // Login struct no more needed, free mem ! ;)
                delete curUser->uLogInOut;
                curUser->uLogInOut = NULL;

            	// PPK ... send all login data from buffer !
            	if(curUser->sbdatalen > 0) {
                    UserTry2Send(curUser);
                }
                    
                // apply one loop delay to avoid double sending of hello and oplist
            	continue;
            }
            case User::STATE_ADDED: {
                if(((curUser->ui32BoolBits & User::BIT_GETNICKLIST) == User::BIT_GETNICKLIST) == true) {
                    UserAddUserList(curUser);
                    curUser->ui32BoolBits &= ~User::BIT_GETNICKLIST;
                }

                // process global data queues
                if(g_GlobalDataQueue->pQueueItems != NULL) {
                    g_GlobalDataQueue->ProcessQueues(curUser);
                }
                
            	if(g_GlobalDataQueue->pSingleItems != NULL) {
                    g_GlobalDataQueue->ProcessSingleItems(curUser);
            	}

                // send data acumulated by queues above
                // if sending caused error, close the user
                if(curUser->sbdatalen != 0) {
                    // PPK ... true = we have rest ;)
                	if(UserTry2Send(curUser) == true) {
                	    iSendRests++;
                	}
                }
                break;
            }
            case User::STATE_CLOSING:
            case User::STATE_REMME:
                continue;
            default:
                if(curUser->sbdatalen > 0) {
                    UserTry2Send(curUser);
                }
                break;
        }
    }

    g_GlobalDataQueue->ClearQueues();

    if(iLoopsForLogins >= 40) {
        dLoggedUsers = 0;
        iLoopsForLogins = 0;
        dActualSrvLoopLogins = 0;
    }

    dActualSrvLoopLogins += (double)SettingManager->iShorts[SETSHORT_MAX_SIMULTANEOUS_LOGINS]/40;
    iLoopsForLogins++;

    iLastSendRest = iSendRests;
    iSendRestsPeak = iSendRests > iSendRestsPeak ? iSendRests : iSendRestsPeak;
}
예제 #16
0
TEST(MallocTests, HeapCompact) {
    HANDLE heap = GetProcessHeap();
    ASSERT_NE(heap, (HANDLE)NULL);
    SIZE_T largest = HeapCompact(heap, 0);
    ASSERT_GT(largest, 1024);
}
예제 #17
0
void
ProcessTimer::SystemProcessTimer()
{
  HeapCompact();
}
예제 #18
0
// Perform a compacting GC
size_t ObjectMemory::compact(Oop* const sp)
{
	TRACE("Compacting OT, size %d, free %d, ...\n", m_nOTSize, m_pOT + m_nOTSize - m_pFreePointerList);
	EmptyZct(sp);

	// First perform a normal GC
	reclaimInaccessibleObjects(GCNormal);

	Interpreter::freePools();

	// Walk the OT from the bottom to locate free entries, and from the top to locate candidates to move
	// 

	size_t moved = 0;
	OTE* last = m_pOT + m_nOTSize - 1;
	OTE* first = m_pOT;
#pragma warning(push)
#pragma warning(disable : 4127)
	while(true)
#pragma warning(pop)
	{
		// Look for a tail ender
		while (last > first && last->isFree())
			last--;
		// Look for a free slot
		while (first < last && !first->isFree())
			first++;
		if (first == last)
			break;	// Met in the middle, we're done
		
		HARDASSERT(first->isFree());
		HARDASSERT(!last->isFree());

		// Copy the tail ender over the free slot
		*first = *last;
		moved++;
		// Leave forwarding pointer in the old slot
		last->m_location = reinterpret_cast<POBJECT>(first);
		last->beFree();
		last->m_count = 0;
		// Advance last as we've moved this slot
		last--;
	}

	HARDASSERT(last == first);
	// At this point, last == first, and the first free slot will be that after last

	TRACE("%d OTEs compacted\n", moved);

	// Now we can update the objects using the forwarding pointers in the old slots

	// We must remove the const. spaces memory protect for the duration of the pointer update
	ProtectConstSpace(PAGE_READWRITE);

	// New head of free list is first OTE after the single contiguous block of used OTEs
	// Need to set this before compacting as 
	m_pFreePointerList = last+1;

	// Now run through the new OT and update the Oops in the objects
	OTE* pOTE = m_pOT;
	while (pOTE <= last)
	{
		compactObject(pOTE);
		pOTE++;
	}

	// Note that this copies VMPointers to cache area
	ProtectConstSpace(PAGE_READONLY);

	// We must inform the interpreter that it needs to update any cached Oops from the forward pointers
	// before we rebuild the free list (which will destroy those pointers to the new OTEs)
	Interpreter::OnCompact();

	// The last used slot will be the slot before the first entry in the free list
	// Using this, round up from the last used slot to the to commit granularity, then uncommit any later slots
	// 
	
	OTE* end = (OTE*)_ROUND2(reinterpret_cast<ULONG_PTR>(m_pFreePointerList + 1), dwAllocationGranularity);

#ifdef _DEBUG
	m_nFreeOTEs = end - m_pFreePointerList;
#endif

	SIZE_T bytesToDecommit = reinterpret_cast<ULONG_PTR>(m_pOT + m_nOTSize) - reinterpret_cast<ULONG_PTR>(end);
	::VirtualFree(end, bytesToDecommit, MEM_DECOMMIT);
	m_nOTSize = end - m_pOT;

	// Now fix up the free list
	OTE* cur = m_pFreePointerList;
	while (cur < end)
	{
		HARDASSERT(cur->isFree());
		cur->m_location = reinterpret_cast<POBJECT>(cur + 1);
		cur++;
	}

	// Could do this before or after check refs, since that can account for Zct state
	PopulateZct(sp);

	CHECKREFERENCES

	HeapCompact();

	TRACE("... OT compacted, size %d, free %d.\n", m_nOTSize, end - m_pFreePointerList);

	Interpreter::scheduleFinalization();

	return m_pFreePointerList - m_pOT;
}