is malloc thread-safe??

I

Ian Collins

¬a\/b said:
i all ears for to hear who can modify "DWORD WINAPI xx(void* a)"
function in the way 88 threads and the 88 loops create some "dead
lock" or something that slow down my dual core cpu more than necessary
WTF is "DWORD WINAPI"?
 
I

Ian Collins

¬a\/b said:
it seems i did some errors in numbering the threads too

but what is the problem with
"my_threadsafe_f" function?

there was someone that said this is not ok in a multi processor pc
but in my dual core windows xp pc all seems ok

#include <stdio.h>
#include <windows.h>
#include <time.h>

#define F for
#define uns unsigned
Isn't it about time you gave up on this bollocks?

<windows specific code snipped>
 
P

Peter J. Holzer

it seems i did some errors in numbering the threads too

but what is the problem with
"my_threadsafe_f" function?

there was someone that said this is not ok in a multi processor pc
but in my dual core windows xp pc all seems ok

"All seems ok" is no guarantuee that all is ok. Code with a race
condition can work perfectly well most of time.

[...]
int __stdcall LockDword(uns* mem, uns NThread);
void __stdcall UnlockDword(uns* mem);

uns resource=0;
uns fine=0;

time_t ti, tf;

void my_threadsafe_f(int siz, void* a)
{unsigned int aa;
static uns here=0;

aa= *(uns*)a; (void) siz;
la:;
Sleep(0);
if( LockDword(&here, aa)==0 || here!=aa)
goto la;
else
{++resource;
UnlockDword(&here);
}
}

In your original example you didn't use the LockDword and UnlockDword
functions. If these functions do what they promise, your code is
probably fine (I haven't really checked it). However, there is no way to
write these functions in portable C. You somehow demonstrate this by
providing assembler source code for these functions. Why were they
written in assembler? Because they cannot be written in C. (A compiler
may provide a way to do it, but then that is specific to this a
compiler).

hp
 
S

santosh

¬a\/b said:
google: stdcall

I'm sure Ian Collins knows what "DWORD WINAPI" and "__stdcall" are. He's
trying to tell you that it's not topical to this group. But then that
hasn't stopped you posting OT material yet.
 
R

Richard

santosh said:
I'm sure Ian Collins knows what "DWORD WINAPI" and "__stdcall" are. He's
trying to tell you that it's not topical to this group. But then that
hasn't stopped you posting OT material yet.

It seemed to me that he wanted to know what they were and asked in a
rude and aggressive manner. *shrug*. Nothing to see here folks.
 
K

Kenny McCormack

google: stdcall

I'm sure Ian Collins knows what "DWORD WINAPI" and "__stdcall" are. He's
trying to tell you that it's not topical to this group. But then that
hasn't stopped you posting OT material yet.[/QUOTE]

In which case, he's a lying sack of crap.
 
¬

¬a\\/b

they should be result in
unsigned __stdcall
WTF is __stdcall?[/QUOTE]

this should be an easier example to port in linux and other
OSes

more than the standard c it has
function of CreateThread, WaitForSingleObject, CloseHandle and
X86>=486 cpu assembly code

it is possible that many cpu not x86 have some instruction good for
threads and so traslate assembly should be easy too

#include <stdio.h>
#include <windows.h>
#include <time.h>

#define F for
#define R return
#define P printf
#define uns unsigned


int __stdcall LockDword(uns* mem, uns NThread);
void __stdcall UnlockDword(uns* mem);

uns resource=0;
uns fine=0;

time_t ti, tf;

void my_threadsafe_f(int siz, void* a)
{unsigned int aa;
static uns here=0;

aa= *(uns*)a; (void) siz;
la:;
Sleep(0);
if( LockDword(&here, aa)==0 || here!=aa)
goto la;
else
{++resource;
UnlockDword(&here);
}
}

uns long __stdcall xx(void* a)
{uns x;
char szMsg[80];

if( *(uns*)a==19)
printf("\nI'm in the thread 19 \n");

// 100000 * 88 = 8800000

F(x=0; x<100000; ++x)
my_threadsafe_f(0, a);
++fine;
return 0;
}


void error_exit(char* a)
{if(a) printf( "%s exit\n", a); exit(0);}


int main( void )
{uns i;
uns long dwThreadId[900];
void *hThread[900];
uns dwThrdParam[900];
char msg[512];
char sg[512];

printf("I'm in main \n");

ti=time(0);
F(i=0; i<88; ++i)
{dwThrdParam=i+1;
hThread = CreateThread(
NULL, // no security attributes
0, // use default stack size
xx, // thread function
(void*) &dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId
);
if(hThread==0)
{sprintf( msg, "ThreadFunct %d Error\n", i);
if(i!=0)
{F(--i;i!=0;--i)
CloseHandle( hThread );
CloseHandle( hThread[0] );
}
error_exit(msg);
}
}

F(i=87; i!=0; --i)
WaitForSingleObject(
hThread, // handle of object to wait for
INFINITE // time-out interval in milliseconds
);
WaitForSingleObject(hThread[0], INFINITE);

tf=time(0);

F(i=0;i<88; ++i); CloseHandle( hThread );

sprintf( sg, "resource=%u ;;; fine=%u time=%g",
resource, fine, difftime(tf, ti) );
P("%s\n", sg);

ti=time(0);
F(i=0; i<88000000; ++i)
resource+=i%30;
tf=time(0);

sprintf( sg, " 2 time=%g %u ",
difftime(tf, ti), resource );
P("%s\n", sg);

R 0;
}

--------------------------------
; nasmw -fobj thisfile.asm

section _DATA public use32 class=DATA
global LockDword, UnlockDword

section _TEXT public use32 class=CODE


; int LockDword(uns* mem, uns NThread)
; Se effettua il lock ritorna 1(CF==0)
; Se non effettua il lock ritorna 0(CF==1)
; NB
; il numero di tread è un valore che varia
; da 1 a UNS_MAX
; il valore 0 significa: "mem" non usata dai thread
; 0c, 4r, 8ra, 12P_mem, 16P_NThread
LockDword:
push ecx
push edx
%define @mem [esp+12]
%define @NThread [esp+16]
mov edx, @mem
xor eax, eax
cmp dword[edx], 0
jne .1
mov ecx, @NThread
lock cmpxchg dword[edx] , ecx
jnz .1
mov eax, 1
clc
jmp short .2
..1: ; 0 CF==1 Error
xor eax, eax
stc
..2: ; 1 CF==0 0k
%undef @mem
%undef @NThread
pop edx
pop ecx
ret 8

; void UnlockDword(uns* mem)
; 0r, 4a, 8ra, 12P_mem
UnlockDword:
push eax
push edx
mov eax, [esp+12]
xor edx, edx
lock xchg [eax] , edx
pop edx
pop eax
ret 4

--------------------------------

C:\Dox>a3
I'm in main

I'm in the thread 19
resource=8800000 ;;; fine=88 time=11
2 time=1 1284799900

the one that use 1 only thread seems 10*11==110 time faster;
there is a way to do better than this with sys lock?

i all ears for to hear who can modify
"uns long __stdcall xx(void* a)"
function in the way 88 threads and the 88 loops create some "dead
lock" or something that slow down my dual core cpu more than necessary

if you are in the comp.lang.c ng you can modify that function use
standard c so we are not ot :)

Please first of speak against it should be better to find an example
of above

thank you very much
 
C

CBFalconer

Bjoern said:
Theoretically not, pracitcally yes.

Nonsense. It depends on the implementation. There are precisely
three critical entry points, via malloc, realloc, and free
(anything else can be reduced to calls on these). If each entry
does the apppropriate things (flags, etc.) to prevent further entry
until after exit, the system is thread-safe.
 
¬

¬a\\/b

#include <stdio.h>
#include <windows.h>
#include <time.h>

#define F for
#define R return
#define P printf
#define uns unsigned


int __stdcall LockDword(uns* mem, uns NThread);
void __stdcall UnlockDword(uns* mem);

uns resource=0;
uns fine=0;

time_t ti, tf;

void my_threadsafe_f(int siz)
{
static uns here=0;
(void) siz;
la:;
Sleep(0);
if( here==1 || LockDword(&here, 1)==0)
goto la;
else
{++resource;
UnlockDword(&here);
}
}

uns long __stdcall xx(void* a)
{uns x;
char szMsg[80];

if( *(uns*)a==19)
printf("\nI'm in the thread 19 \n");

// 100000 * 88 = 8800000

F(x=0; x<100000; ++x)
my_threadsafe_f(0);
++fine;
return 0;
}


void error_exit(char* a)
{if(a) printf( "%s exit\n", a); exit(0);}


int main( void )
{uns i;
uns long dwThreadId[900];
void *hThread[900];
uns dwThrdParam[900];
char msg[512];
char sg[512];

printf("I'm in main \n");

ti=time(0);
F(i=0; i<88; ++i)
{dwThrdParam=i+1;
hThread = CreateThread(
NULL, // no security attributes
0, // use default stack size
xx, // thread function
(void*) &dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId
);
if(hThread==0)
{sprintf( msg, "ThreadFunct %d Error\n", i);
if(i!=0)
{F(--i;i!=0;--i)
CloseHandle( hThread );
CloseHandle( hThread[0] );
}
error_exit(msg);
}
}

F(i=87; i!=0; --i)
WaitForSingleObject(
hThread, // handle of object to wait for
INFINITE // time-out interval in milliseconds
);
WaitForSingleObject(hThread[0], INFINITE);

tf=time(0);

F(i=0;i<88; ++i); CloseHandle( hThread );

sprintf( sg, "resource=%u ;;; fine=%u time=%g",
resource, fine, difftime(tf, ti) );
P("%s\n", sg);

ti=time(0);
F(i=0; i<88000000; ++i)
resource+=i%30;
tf=time(0);

sprintf( sg, " 2 time=%g %u ",
difftime(tf, ti), resource );
P("%s\n", sg);

R 0;
}

--------------------------------
; nasmw -fobj thisfile.asm

section _DATA public use32 class=DATA
global LockDword, UnlockDword

section _TEXT public use32 class=CODE


; int LockDword(uns* mem, uns NThread)
; Se effettua il lock ritorna 1(CF==0)
; Se non effettua il lock ritorna 0(CF==1)
; NB
; il numero di tread è un valore che varia
; da 1 a UNS_MAX
; il valore 0 significa: "mem" non usata dai thread
; 0c, 4r, 8ra, 12P_mem, 16P_NThread
LockDword:
push ecx
push edx
%define @mem [esp+12]
%define @NThread [esp+16]
mov edx, @mem
xor eax, eax
cmp dword[edx], 0
jne .1
mov ecx, @NThread
lock cmpxchg dword[edx] , ecx
jnz .1
mov eax, 1
clc
jmp short .2
.1: ; 0 CF==1 Error
xor eax, eax
stc
.2: ; 1 CF==0 0k
%undef @mem
%undef @NThread
pop edx
pop ecx
ret 8

; void UnlockDword(uns* mem)
; 0r, 4a, 8ra, 12P_mem
UnlockDword:
push eax
push edx
mov eax, [esp+12]
xor edx, edx
lock xchg [eax] , edx
pop edx
pop eax
ret 4

--------------------------------

C:\Dox>a3
I'm in main

I'm in the thread 19
resource=8800000 ;;; fine=88 time=11
2 time=1 1284799900


i see that all you like much to speak
why not speak here and say what not goes ok here?

some time ago someone said that in a dual cpu this can not work well
than i have a dual cpu (because my first pc was gone) and all seeems
ok

now is the time to speak
is the comp.prgramming.threads dead group or not?
 
D

David Schwartz

[snip]

Every couple of months, someone has to re-invent a synchronization
primitive that has every possible mistake it is possible to make. This
is precisely what you have done. I will only point out what I consider
to be the most awful mistake:

la:;
Sleep(0);
if( LockDword(&here, aa)==0 || here!=aa)
goto la;
(Where 'LockDword' spins on a 'lock cmpxchg')

Consider if two CPUs is in this tight loop and another CPU holds the
lock. The call to 'Sleep(0)' is basically a no-op, since there is
nothing for this CPU to yield to -- the only runnable thread is
already running on the other CPU.

The CPU is much faster than the FSB, so the rate at which these CPUs
can run will be limited by how fast they can do a 'lock cmpxchg'. That
is, they will saturate the FSB ping-ponging the dword they are trying
to lock back and forth.

So while two threads are uselessly saturating the FSB with complete
garbage, the only thread doing useful work has to compete for the FSB.
If it's lucky, it gets 1/3 of it.

When the lock finally is released, whichever CPU gets the lock will
suffer the worst possible branch misprediction and will likely have to
start its pipelines over from scratch.

Another problem is if the CPU is hyper-threaded. Even with only two
logical CPUs, one logical CPU will be in a maxed out tight loop while
the other is trying to get useful work done. It will run at half speed
or so as the other CPU gets useless spinning done as fast as possible.

In other words, you have created almost the worst imaginable
synchronization primitive. Please don't take this the wrong way --
everyone does it wrong the first time. Getting it right is *really*
hard.

DS
 
R

Richard Bos

David Schwartz said:
[snip]

Every couple of months, someone has to re-invent a synchronization
primitive that has every possible mistake it is possible to make.

And generally, that someone is the same troll again and again.
 
¬

¬a\\/b

In other words, you have created almost the worst imaginable
synchronization primitive. Please don't take this the wrong way --
everyone does it wrong the first time. Getting it right is *really*
hard.

i thought of write a malloc thread safe but now i think that the sys
malloc of the OS (operative system) has to be tread safe: end.

i think that for to write a safe thread function i have to use OS
functions because is the OS that decide how and where use the cpu
excuse me if i speak too much and thank you very much :)
 
C

Chris Thomasson

¬a\/b said:
i thought of write a malloc thread safe but now i think that the sys
malloc of the OS (operative system) has to be tread safe: end.
[...]

The malloc of a given multi-threaded platform will most likely be
thread-safe indeed. As for creating your own malloc, well, this "can be
worthwhile" because a 100% thread-safe implementation can be realized
without using any mutual exclusion.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,153
Latest member
NamKaufman
Top