Memory usage in hazard pointer queue application - c++

I have recently testing queue with hazard pointer application as below :
https://github.com/chergert/dukes_of_hazard
I have noticed that RES raise quite fast in my own test ap ,
MEMORY-ERROR: [30770]: GSlice: failed to allocate 120 bytes (alignment: 128): Cannot allocate memory
happened in the end , the ap has 5 threads to enqueue , 5 threads to dequeue and then
send to 5 socket server each thread , like following :
#include "lf-queue.h"
typedef struct People_
{
int age ;
char name[16] ;
double income ;
} People ;
#define NUM 20000000
LfQueue *q ;
int GlbCnt,GlbRow ;
int iConn[5] ;
int main()
{
q = lf_queue_new();
g_thread_init(NULL);
if(DoConnect() != 1)
{
printf("Error in connect server .exe , port=5566,5567,5568,5569,5570 ! \n") ;
exit(0) ;
}
pthread_t tid1[5],tid2[5];
int icnt1[5] = {0,1,2,3,4} ;
int icnt2[5] = {0,1,2,3,4} ;
void *func1(void *);
void *func2(void *);
for(int idx=0;idx<5;idx++)
{
pthread_create(&tid1[idx], NULL, &func1 , (void *) icnt1[idx] );
pthread_create(&tid2[idx], NULL, &func2 , (void *) icnt2[idx] );
}
while(1){
printf("Done(%d)\n",GlbCnt) ;
sleep(1) ;
}
} //main
void *func1(void * inum)
{
int ithread = (long)(int) inum ;
pthread_detach(pthread_self());
People* p ;
while(1){
for(int idx=0;idx<NUM;idx++){
usleep(1) ;
p = (People *) malloc( sizeof(People) ) ;
p->age = __sync_add_and_fetch(&GlbRow,1) ;
sprintf(p->name,"%s%08d","NAME",p->age ) ;
p->income = p->age * 1.0 ;
lf_queue_enqueue(q,p) ;
}
break ;
} //while
}
void *func2(void * inum)
{
int ithread = (long)(int) inum ;
pthread_detach(pthread_self());
People* p ;
while(1){
usleep(1) ;
p = (People *) lf_queue_dequeue(q) ;;
if(p){
char line[128]={0} ;
sprintf(line,"%010d|%s|%010.0f|",p->age,p->name,p->income) ;
if (send(iConn[ithread],line,35,MSG_NOSIGNAL)<0){
printf("send error \n");
exit( 0 ) ;
}
__sync_add_and_fetch(&GlbCnt,1) ;
free(p) ;
}
} //while
}

Related

C++ JNI open /dev/rtc result invalid argument

I try to open /dev/rtc or /dev/rtc0 .
# ls -l /dev/rtc*
lrwxrwxrwx 1 root root 4 Aug 11 05:59 /dev/rtc -> rtc0
crw------- 1 root root 248, 0 Aug 11 05:59 /dev/rtc0
this is my JNI code (C++):
using namespace std;
void get_system_dt(struct tm tm) {
time_t t = time(NULL);
tm = *localtime(&t) ;
}
int set_hardware_dt() {
struct tm tm ;
get_system_dt(tm);
struct rtc_time rt ;
rt.tm_year = tm.tm_year ;
rt.tm_min = tm.tm_mon ;
rt.tm_yday = tm.tm_yday ;
rt.tm_mday = tm.tm_mday ;
rt.tm_hour = tm.tm_hour ;
rt.tm_wday = tm.tm_wday ;
rt.tm_min = tm.tm_min ;
rt.tm_sec = tm.tm_sec ;
rt.tm_isdst = tm.tm_isdst ;
int fd = open ("/dev/rtc0",O_RDONLY); <-- Problem this line
cout << fd << endl;
if (fd != 3) {
perror("SET_HW_DT");
return 1;
}
int r = ioctl(fd,RTC_SET_TIME,&rt);
if (r != 0) {
perror("ioctl");
return 1;
}
close(fd);
return 0 ;
}
JNIEXPORT void JNICALL Java_ir_moke_jsysbox_time_JDateTime_syncSystemToHardware (JNIEnv *env, jclass clazz) {
int r = set_hardware_dt();
if (r != 0) throwException(env,"Failed to sync system to hardware");
}
and this output :
6
SET_HW_DT: Invalid argument
I can not understand why this code result Invalid argumnt !
that code with simple main do work without any problem :
int main(int argc, char *argv[])
{
set_hardware_dt();
return 0;
}
output :
3
SET_HW_DT: Success
What is problem ?
Your code has several problems. From top to bottom:
void get_system_dt(struct tm tm)
will never modify the tm you pass in in set_hardware_dt. You need to pass a struct tm& tm for that code to work.
Next, a typo:
rt.tm_min = tm.tm_mon ;
Finally, your "problem this line" is not actually the problem.
Instead, this line is:
if (fd != 3) {
This assumes that the freshly-allocated file descriptor will be number 3. This is typically only the case in small programs that did not open or close any file descriptors before your code runs.
Instead, you should check whether fd is negative, as that is the error signal from open.

RtAudio: understanding frame count vs buffer size

Looking at the duplex example from the documentation of RtAudio, I do not understand why the number of frames has to be multiplied by 8 to get the good buffer size to copy.
In the example there is bufferBytes = bufferFrames * 2 * 4;. I imagine the * 2 refers to the number of channels, but I see no reason for the * 4.
Whole example:
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
// Pass-through function.
int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *data )
{
// Since the number of input and output channels is equal, we can do
// a simple buffer copy operation here.
if ( status ) std::cout << "Stream over/underflow detected." << std::endl;
unsigned int *bytes = (unsigned int *) data;
memcpy( outputBuffer, inputBuffer, *bytes );
return 0;
}
int main()
{
RtAudio adac;
if ( adac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 0 );
}
// Set the same number of channels for both input and output.
unsigned int bufferBytes, bufferFrames = 512;
RtAudio::StreamParameters iParams, oParams;
iParams.deviceId = 0; // first available device
iParams.nChannels = 2;
oParams.deviceId = 0; // first available device
oParams.nChannels = 2;
try {
adac.openStream( &oParams, &iParams, RTAUDIO_SINT32, 44100, &bufferFrames, &inout, (void *)&bufferBytes );
}
catch ( RtAudioError& e ) {
e.printMessage();
exit( 0 );
}
// THIS HERE...
//
bufferBytes = bufferFrames * 2 * 4; // <---- WHY * 4??
//
//
try {
adac.startStream();
char input;
std::cout << "\nRunning ... press <enter> to quit.\n";
std::cin.get(input);
// Stop the stream.
adac.stopStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
cleanup:
if ( adac.isStreamOpen() ) adac.closeStream();
return 0;
}

pthread_attr_setinheritsched for sched_setscheduler

I try to test one application which will run several threads with different priority , so the following is my test ap , run in linux x86_64 :
pthread_spinlock_t orderspinlock ;
int iGlbCnt=0 ;
void * donothing(void *arg)
{
pthread_attr_t attr;
pthread_attr_init (&attr);
//int s = pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED );
int s = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED );
if( s != 0 ){
printf("pthread_attr_setinheritsched error \n");
exit(0) ;
}
int ipriority = (int)(long) arg ;
const char *sched_policy[] = {
"SCHED_OTHER",
"SCHED_FIFO",
"SCHED_RR",
"SCHED_BATCH"
};
struct sched_param sp = {
.sched_priority = ipriority
};
pid_t pid = getpid();
printf("pid=(%d)\n",pid);
sched_setscheduler(pid, SCHED_RR, &sp);
printf("Scheduler Policy is %s.\n", sched_policy[sched_getscheduler(pid)]);
pthread_detach(pthread_self());
int icnt=0;
while(1){
usleep( 1 ) ;
pthread_spin_lock(&orderspinlock) ;
iGlbCnt++ ;
pthread_spin_unlock(&orderspinlock) ;
if( ++icnt > 10000000 )
break;
}
printf("thread done...(%d)\n",iGlbCnt);
}
int main(int argc, char **argv)
{
pthread_spin_init(&orderspinlock, 0);
pthread_attr_t attr;
pthread_attr_init (&attr);
//int s = pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED );
int s = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED );
if( s != 0 ){
printf("pthread_attr_setinheritsched error \n");
exit(0) ;
}
pthread_t tid;
pthread_create(&tid, NULL, &donothing, (void *)(long) 80);
pthread_create(&tid, NULL, &donothing, (void *)(long) 10);
while( 1 )
sleep( 5 ) ;
}
and g++ --std=c++11 y.cpp -pthread -o y.exe
run :
sudo chrt -r -v 66 ./y.exe
another terminal watch the threads by
top -H -p `pidof y.exe`
I see the threads PR are -67 , -67 , -11 , after both donothing threads die ,
the main thread PR = -11 , What should I do so that all three threads
priority are -81 , -11 , -67 and the main thread keep in -67 to the end ?!
Edit :
int policy = 2 ;
s = pthread_setschedparam(pthread_self(),policy,&sp) ;
instead of :
pid_t pid = getpid();
sched_setscheduler(pid, SCHED_RR, &sp);
look work fine to me .

g++ compiler with/without -O2

I have the following source compiled by g++ 4.8.2 :
g++ --std=c++11 testx.cpp -pthread -lrt -O2 -o testx.exe
g++ --std=c++11 testx.cpp -pthread -lrt -o testy.exe
layout.h :
#pragma once
typedef struct DBInfo_
{
volatile int seqno ;
char groupname[32] ;
char action[32] ;
int booklayer ;
} DBInfo ;
#define DBARRAYSIZE 100
static DBInfo *conf;
#define STATE_FILE "/strategy2/test.shared"
testx.cpp :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/file.h>
#include <ctype.h>
#include <pthread.h>
#include <sys/stat.h>
#include <assert.h>
#include "layout.h"
int g_DBSharedMemIdx = 0 ;
volatile int iGlbErrorSeqLock = 0 ;
void create_shmem(void)
{
int shm_fd;
if((shm_fd = shm_open(STATE_FILE, (O_CREAT | O_EXCL | O_RDWR),
(S_IREAD | S_IWRITE))) > 0 ) {
printf("O_CREAT | O_EXCL | O_RDWR \n"); /* We are the first instance */
}
else if((shm_fd = shm_open(STATE_FILE, (O_CREAT | O_RDWR),
(S_IREAD | S_IWRITE))) < 0)
{
printf("Could not create shm object. \n");
exit( 0 ) ;
}
int iTotalByte = sizeof(DBInfo)*DBARRAYSIZE ;
ftruncate(shm_fd, iTotalByte );
conf = (DBInfo*) mmap(0, iTotalByte , (PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0) ;
if(conf == MAP_FAILED)
{
printf(" mmap error ....\n") ;
exit( 0 ) ;
}
g_DBSharedMemIdx = 0 ;
(conf+g_DBSharedMemIdx)->seqno = 0 ;
strcpy( (conf+g_DBSharedMemIdx)->groupname,"" ) ;
strcpy( (conf+g_DBSharedMemIdx)->action,"" ) ;
(conf+g_DBSharedMemIdx)->booklayer = 0 ;
}//create_shmem
int getDBInfo(DBInfo& pDBInfo)
{
if( pDBInfo.seqno == (conf+g_DBSharedMemIdx)->seqno)
return 0 ;
volatile int ilocalseqno1 = 0 , ilocalseqno2 = 0 ;
volatile int icnt=0;
while( 1 ){
icnt++ ;
if( icnt >= 10000 ){
iGlbErrorSeqLock = 1 ;
break ;
}
ilocalseqno1 = (conf+g_DBSharedMemIdx)->seqno ;
if( ilocalseqno1 % 2 ){
printf("***************************************************************************** \n");
continue;
}
strcpy( pDBInfo.action,(conf+g_DBSharedMemIdx)->action ) ;
pDBInfo.booklayer = (conf+g_DBSharedMemIdx)->booklayer ;
ilocalseqno2 = (conf+g_DBSharedMemIdx)->seqno ;
if( ilocalseqno1 != ilocalseqno2 ){
printf("***************************************************************************** \n");
continue;
}
pDBInfo.seqno = ilocalseqno2 ;
break ;
} //while
if( iGlbErrorSeqLock == 1 )
return -1 ;
return 1 ;
}//getDBInfo
void *ThreadONE(void *param)
{
printf("TestThread...(%p)\n",param) ;
pthread_detach(pthread_self());
while( 1 ){
(conf+g_DBSharedMemIdx)->seqno++ ;
strcpy( (conf+g_DBSharedMemIdx)->groupname,"group1" ) ;
strcpy( (conf+g_DBSharedMemIdx)->action,"RUN" ) ;
(conf+g_DBSharedMemIdx)->booklayer = 3 ;
if( (conf+g_DBSharedMemIdx)->seqno % 2 == 1 )
(conf+g_DBSharedMemIdx)->seqno++ ;
usleep( 1 ) ;
}//while
}//ThreadONE
void *ThreadTWO(void *param)
{
DBInfo pDBInfo ;
printf("TestThread...(%p)\n",param) ;
pthread_detach(pthread_self());
int icnt = 0 ;
while( 1 ){
int iret = getDBInfo(pDBInfo);
if( iret < 0 ){
printf("iGlbErrorSeqLock happened \n") ;
assert( iGlbErrorSeqLock == 100 );
}else if(iret == 1){
icnt++ ;
//printf("icnt=(%d)\n",icnt);
}
usleep( 1 ) ;
}//while
}//ThreadTWO
int main(int argc, char** argv)
{
create_shmem();
sleep( 1 ) ;
pthread_t tid ;
pthread_create(&tid , NULL, ThreadONE, (void*)(long)3);
pthread_create(&tid , NULL, ThreadTWO, (void*)(long)3);
while( 1 )
sleep( 5 ) ;
} //main
testy.exe(compiled without -O2) run will see "**************" 2 times per second ,
testx.exe(compiled with -O2) run will see "***********" not quite easy .
I have this test because in my original source , sometimes call function
like getDBInfo will be trapped in endless loop if compiled with -O2,
and it will be fine without -O2 , so I am curious what compiler do in
getDBInfo function and what should I do according to it .

How to get stacktrace for all threads running in a process?

I am trying to get stack trace for a process running with multiple threads, I am able to get the stack trace for main thread. But for other threads(belongs to same process), even though i used proper threadIds, I am getting the same stacktrace for all threads(same as main thread). I am sure those are not correct traces for that threads.
following is the code, I have no idea what went wrong. If you have any idea please let me know. Thanks..
My pExPtrs is null, i am not calling this during exception.
void DoStackTraces ( LPTSTR szString,DWORD dwSize, EXCEPTION_POINTERS *pExPtrs)
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, static_cast<DWORD>(getpid()));
if (h != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
if(te.th32OwnerProcessID == static_cast<DWORD>(getpid())) {
std::cout << "Process 0x%04x | Thread 0x%04x\n"
<< te.th32OwnerProcessID << " | " << te.th32ThreadID
<< " Current ProcessID : " << getpid()
<< " dwSize : " << dwSize
<< " pExPtrs : " << pExPtrs
<< std::endl;
HANDLE hnd = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, te.th32ThreadID);
SuspendThread(hnd);
DoStackTraceThread(hnd,szString,dwSize,0);
ResumeThread(hnd);
std::cout << szString << std::endl;
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
//HANDLE hThread = GetCurrentThread();
//DoStackTraceThread (hThread, szString,dwSize,pExPtrs);
}
void DoStackTraceThread ( HANDLE hThread, LPTSTR szString ,
DWORD dwSize , EXCEPTION_POINTERS *pExPtrs)
{
if (g_bCsysDontGetProcessCritSec){return;}
sAutoLock al(g_stackTraceMux); // The code probably isn't thread safe.
if (g_cSym.isInstalled() == false) return;
HANDLE hProcess = GetCurrentProcess ( ) ;
// If the symbol engine is not initialized, do it now.
if ( FALSE == g_bSymIsInit )
{
DWORD dwOpts = APFSymGetOptions ( ) ;
// Turn on load lines.
APFSymSetOptions ( dwOpts |
SYMOPT_LOAD_LINES ) ;
if ( FALSE == g_cSym.SymInitialize ( hProcess ,
NULL ,
TRUE ) )
{
std::cerr << "APF ERROR: DiagAssert : Unable to initialize the "
"symbol engine!!!" << std::endl;
}
else
{
g_bSymIsInit = TRUE ;
}
}
// The symbol engine is initialized so do the stack walk.
// The array of addresses.
ADDRVECTOR vAddrs ;
// The thread information.
CONTEXT stCtx ;
CONTEXT *pstCtx ;
GET_CURRENT_CONTEXT(stCtx, CONTEXT_FULL);
{
STACKFRAME64 stFrame ;
DWORD dwMachine ;
ZeroMemory ( &stFrame , sizeof ( STACKFRAME64 ) ) ;
stFrame.AddrPC.Mode = AddrModeFlat ;
if (pExPtrs)
{
pstCtx=pExPtrs->ContextRecord;
}
else {
pstCtx=&stCtx;
}
dwMachine = IMAGE_FILE_MACHINE_I386 ;
if (pExPtrs){
stFrame.AddrPC.Offset = pstCtx->Eip ;
stFrame.AddrStack.Offset = pstCtx->Esp ;
stFrame.AddrFrame.Offset = pstCtx->Ebp ;
}
else {
stFrame.AddrPC.Offset = stCtx.Eip ;
stFrame.AddrStack.Offset = stCtx.Esp ;
stFrame.AddrFrame.Offset = stCtx.Ebp ;
}
stFrame.AddrStack.Mode = AddrModeFlat ;
stFrame.AddrFrame.Mode = AddrModeFlat ;
// Loop for the first 512 stack elements.
for ( DWORD i = 0 ; i < 512 ; i++ )
{
if ( FALSE == StackWalkProc ( dwMachine ,
hProcess ,
hThread ,
&stFrame ,
pstCtx ,
NULL ,
(PFUNCTION_TABLE_ACCESS_ROUTINE64)
APFSymFunctionTableAccess ,
GetModBase ,
NULL ) )
{
break ;
}
// Also check that the address is not zero. Sometimes
// StackWalk returns TRUE with a frame of zero.
if ( 0 != stFrame.AddrPC.Offset )
{
vAddrs.push_back ( stFrame.AddrPC.Offset ) ;
}
}
// Now start converting the addresses.
DWORD64 dwSizeLeft = dwSize ;
DWORD64 dwSymSize ;
TCHAR szSym [ MAX_PATH * 2 ] ;
LPTSTR szCurrPos = szString ;
ADDRVECTOR::iterator loop ;
for ( loop = vAddrs.begin ( ) ;
loop != vAddrs.end ( ) ;
loop++ )
{
dwSymSize = DoConvertAddress ( *loop , szSym ) ;
if ( dwSizeLeft <= dwSymSize )
{
break ;
}
_tcscpy ( szCurrPos , szSym ) ;
szCurrPos += dwSymSize ;
dwSizeLeft -= dwSymSize ;
}
}
}
The handle to the thread snapshot is not the same thing as the handle to the thread. Calling Suspend/ResumeThread on the snapshot handle is incorrect (and if it weren't it could be dangerous, what if you SuspendThread this thread?). You need to OpenThread with the thread id to get a handle that can be used with StackWalk64.
Likewise, assuming GET_CURRENT_CONTEXT operates on the current thread it will not be correct. If it works on hnd, it again won't work because again, that's not the thread handle.