LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-20-2016, 02:56 PM   #1
DeeDeeK
Member
 
Registered: Jan 2016
Distribution: Ubuntu 14.04
Posts: 37

Rep: Reputation: Disabled
Please help me use condition variables in the lthread library!


http://lthread.readthedocs.io/en/latest/intro.html

I have written a slightly complex application which uses pthreads and lthread to asynchronously update information for displaying graphics which represent the goings on of a complex system. One thread per graphic element-very much like sprites. It's not necessary to synchronize the display of these sprites, so that's not the question.

I'd resisted the (very good, helpful) suggestion of using a condition variable to signal the threads to wake. It's become unnecessary for them to busy-wait since, but I'd like to learn to use the lthread_cond_wait and lthread_cond_broadcast functions and simply cannot figure it out.

lthread uses pthreads and plays well with them. I can compile using or not using pthreads and have the same problem.

And may I be clear that I'm looking for suggestion about making lthread work, not for suggestions to use pthreads alone, or even to use another lightweight thread library.

I simply wish to learn the use of condition variables in lthread. I've learned how to use them in pthreads, thanks to the great book, "Linux Programming Interface_ A Linux and UNIX System Programming Handbook, The - Michael Kerrisk." So I'm confused. lthread seems to be as simple. Or simpler.

The following variable has global scope:

Code:
lthread_cond_t *makemore
the function with creates and launches the lthreads dynamically initializes the condition variable using this call:

Code:
lthread_cond_create(&makemore);
Then it creates and launches the threads.

The individual threads then do their thing and wait, calling:

Code:
lthread_cond_wait(makemore,0);
The second value passed is how many milliseconds to sleep- 0 indicating indefinitely, until signaled to awaken. They cooperatively multithread, so the lthread scheduler is supposed to wake 'em up, I think, when this function is called:

Code:
lthread_cond_broadcast(makemore);
instead of that, it crashes or hangs. If I broadcast from within an lthread running on a separate scheduler from the lthreads waiting on the signal, it all crashes. with segmentation fault. From an lthread running on the same scheduler, everydarnthing just stops.

I'm not sure what other information to include. Suggestions for further info to provide or how to make this work would be so welcomed.

by the by, I must apologize to sundialsvcs for not taking this suggestion I quote here right away. This suggestion IS simpler. I just don't know how to get it working.

Quote:
Condition-variables are a good way to do this sort of thing in traditional threading systems. They are, in effect, "the little red flag on the mailbox," which indicates to the driver that the box should be opened because it might have a piece of outbound mail in it.

Last edited by DeeDeeK; 12-20-2016 at 02:58 PM.
 
Old 12-21-2016, 08:24 PM   #2
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by DeeDeeK View Post
I'm not sure what other information to include. Suggestions for further info to provide or how to make this work would be so welcomed.
The code you posted in isolation looks correct. I suggest posting a Short, Self Contained, Correct (Compilable), Example.
 
Old 01-24-2017, 08:15 PM   #3
DeeDeeK
Member
 
Registered: Jan 2016
Distribution: Ubuntu 14.04
Posts: 37

Original Poster
Rep: Reputation: Disabled
I wrote a short program distilling the puzzle that's been bugging me. It creates a pthread, which then creates and launches twenty lightweight threads using the lthread library.

I almost forgot, this is not a standard library and may not be that commonly in use, regardless how great it is. I found it here, downloaded the source and compiled, simply following the directions and it worked first time. I'm using a 64bit amd/intel computer with Ubuntu 15.10.

https://github.com/halayli/lthread

If the environment variable usecondsig is not 0, it will create either another lthread, OR a pthread - either of which broadcast an lthread_cond_t signal to tell the twenty theads to report their numbers ten times, then to quit.

If the environment variable pthreadsig is set to nonzero, a pthread will be used to broadcast the lthread_cond_t variable, otherwise an lthread will to the job

However, if lthread_cond_broadcast() is called from the pthread, it all crashes with a segfault.

I hope that's at least sort of clear. There are all kinds of reasons for doing this, and I'm not interested in why or why not, just how.

I mentioned the use of two environment variables: pthreadsig to choose what calls lthread_cond_broadcast(), and usecondsig to control whether to call it at all.

If you set usecondsig to zero, you can watch the behavior of the threads indefinitely since they won't be signaled.

A third environment variable is useful: randquit -set to non-zero and the lthreads will have a one in fifty chance of quitting every time they loop, so if you don't send a signal with a condition variable to tell them to quit, they'll quit eventually anyhow

The threads print out what they're doing so you can see their behavior in the terminal window, or from a real terminal, you invoke thxc from.

OK, this is my first attempt to post a serious question plus a compilable code example, and I hope I've made it clear and workable. I've compiled and tested this code just as I've posted it, using the same command line, emm, command to gcc to compile it as I posted. In fact I just cut and paste, so I'm very sure it'll work.

Tho the code isn't my actual project-which is too too long for here-it was really good for me to try to distill the thread handling stuff here. It's definitely helped me think and I think maybe you must call the lthread_cond_create() function from the same pthread as the scheduler is running on, which really bugs me so I hope I'm wrong. Other than that, this lthread stuff is hunky-dory by me!

here is how I compile the code from command line

Code:
gcc  --std=gnu11 -D_REENTRANT -pthread  -Wall threadxample.c -o thxc  -llthread `PKG_CONFIG_PATH=/usr/x86_64-linux-gnu;`
Here is the code I compile:

Code:
#include <lthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

/*each lthread which will wait for that signal, and report **
** its serial number is represented in, and passed a copy ***
** of this struct. I hope it's self explanatory enough***/

typedef struct whatiam{
		int 			serialnumber;
		lthread_cond_t		*mysignal;
		char			**myinstructions;
		lthread_t		*my_lightweight_thread_variable;
} me_t;

lthread_t	*an_lthread_signals;
pthread_t	a_pthread_signals;

/*these globals are set through environment variables***
** with the exact same spelling.*/

int pthreadsig,  //1=broadcast cond variable from in a pthread
	randquit,  //1=lthreads will quit eventually at random
	usecondsig;  //0=don't broadcast condition variable

lthread_cond_t	*serialnumber_lthread_wakeup_signal;

char *set_to_quit_or_not = "don't quit";

const int yes = 1,
	no = 0;

//returns from 0 to maximum
// generate random numbers for sleep and wait functions
int
intrand( int maximum ){
  if (!maximum)return 0;
  unsigned long intermediate = rand();
  intermediate *= (abs(maximum)+1);
  intermediate /= INT_MAX;
  return (int)intermediate;
}

void lthread_thread(void *who_I_am){
	me_t *myself = who_I_am;
	for(;;){
		int report = lthread_cond_wait(myself->mysignal, intrand(20)+1);
                //nonblocking sleep from 1 to 21 millisecond for signal then resumes
		if (!report){//return of zero means woke from the signal
			if(!strcmp("quit", *myself->myinstructions)){
				printf("serial number:\t %i\tSIGNALLED TO QUIT!\n\n", myself->serialnumber);
				break;
			}else{
				printf("serial number:\t %i\treporting!\t", myself->serialnumber);
			}
		}else if (report==-2){  // if the lthread_cond_wait times out it reports -2
				printf("timed out!!!:\t %i\ttimed out!!!\t", myself->serialnumber);
			}else{ // other return values not defined in the API
				printf("\n\nabnormal return from lthread_cond_wait\n\n");
				break;
			}
			if((randquit)&&(intrand(50)>49)){ //random quitting helpful if no cond. signal is broadcast
				printf("\nserial number:\t %i\tQUITTING AT RANDOM!!!\n", myself->serialnumber);
				break;
			}
		}
		return;
}

void *pthread_signals_controls_lthreads(void *unused){
// the loop below should make the threads report their numbers
	for(int i = 0; i < 10; i++){
		usleep(50000);// nonblocking sleep for 20ms (20000us)
		printf("\n\npthread is now calling lthread_cond_broadcast() to signal lthreads to report\n\n");
		lthread_cond_broadcast(serialnumber_lthread_wakeup_signal);
	}
	// now they should all report quitting and serial numbers
	set_to_quit_or_not = "quit";
	printf("\n\npthread is now calling lthread_cond_broadcast() to signal lthreads to quit\n\n");
	lthread_cond_broadcast(serialnumber_lthread_wakeup_signal);
	printf("\n\nlthread_cond_broadcast() has returned now the lthreads should be quitting\n\n");
	return NULL;
}

void lthread_signals_controls_lthreads(void *unused){
	for(int i = 0; i < 10; i++){
		printf("\n\nlthread is now calling lthread_cond_broadcast() to signal lthreads to report\n\n");
		lthread_cond_broadcast(serialnumber_lthread_wakeup_signal);
		lthread_sleep(50);// nonblocking sleep for 20 ms
	}
	// now they should all report quitting and serial numbers
	set_to_quit_or_not = "quit";
	printf("\n\nlthread is now calling lthread_cond_broadcast() to signal lthreads to quit\n\n");
	lthread_cond_broadcast(serialnumber_lthread_wakeup_signal);
	printf("\n\nlthread_cond_broadcast() has returned now the lthreads should be quitting\n\n");

	return NULL;
}


void *pthread_launches_lthreads(void *unused){
	lthread_cond_create(&serialnumber_lthread_wakeup_signal);
	const int number_of_lthreads = 20;
	set_to_quit_or_not = "don't quit";
	me_t	*array_of_lthreads = malloc(number_of_lthreads*sizeof(me_t));
	for (int i = 0; i < number_of_lthreads; i++){
		array_of_lthreads[i].serialnumber = i;
		array_of_lthreads[i].mysignal = serialnumber_lthread_wakeup_signal;
		array_of_lthreads[i].myinstructions = &set_to_quit_or_not;
/* The thread is represented by this:
array_of_lthreads[i].my_lightweight_thread_variable
the function serving as the start of the thread is
lthread_thread the data passed to the thread is a
structure: &array_of_lthreads[i]
alternately array_of_lthreads+i could have been used*/
		lthread_create(&array_of_lthreads[i].my_lightweight_thread_variable, lthread_thread, &array_of_lthreads[i]);
	}
	if((usecondsig)&&(pthreadsig)){
		pthread_create(&a_pthread_signals, NULL, pthread_signals_controls_lthreads, NULL);
	}else if(usecondsig){
		lthread_create(&an_lthread_signals, lthread_signals_controls_lthreads, NULL);
	}
/*the next function starts the lthread scheduler which will
schedule all the lthreads created using lthread_create within
this pthread. You can also create lthreads and run them from
main();
once the lthread scheduler is running the pthread is effectively paused until all the lthreads exit*/
	lthread_run();
	printf("\n\nthe lthread scheduler has run out of lthreads to schedule\n\n");
	return NULL;
}


int main(int argc, char **argv){


	char *envvar = getenv("pthreadsig");
	pthreadsig = envvar ? atoi(envvar): yes;

 	envvar = getenv("randquit");
	randquit = envvar ? atoi(envvar): no;

	envvar = getenv("usecondsig");
	usecondsig = envvar ? atoi(envvar): no;

	pthread_t	create_launch_lthreads;

	pthread_create(&create_launch_lthreads, NULL, pthread_launches_lthreads, NULL);

	pthread_join(create_launch_lthreads, NULL);
	return 0;
}

Last edited by DeeDeeK; 01-24-2017 at 10:26 PM. Reason: adding url for lthread source, documentation, so you can download and compile
 
Old 01-24-2017, 10:31 PM   #4
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by DeeDeeK View Post
I think maybe you must call the lthread_cond_create() function from the same pthread as the scheduler is running on
Yeah, that seems very likely to me. In the diagram at http://lthread.readthedocs.io/en/latest/intro.html each pthread has it's own separate set of lthreads, with no interaction between them. And http://lthread.readthedocs.io/en/lat...-compute-begin says:

Quote:
Resumes lthread inside a pthread to run expensive computations or make a blocking call like gethostbyname(). This call must be followed by lthread_compute_end() after the computation and/or blocking calls statements have been made, to resume the lthread in its original lthread scheduler. No lthread_* calls can be made during the 2 calls.
I.e., while the lthread is running in a different pthread, you can't use any lthread functions.
 
Old 01-25-2017, 04:00 PM   #5
DeeDeeK
Member
 
Registered: Jan 2016
Distribution: Ubuntu 14.04
Posts: 37

Original Poster
Rep: Reputation: Disabled
putttng two and two together!

I had overlooked that fact, that you can't invoke lthread calls from within the pthread which lthread_compute_begin() and lthread_compute_end()! Very obvious but I wasn't looking there.

I was just imagining that a condition variable must be global-and I guess by declaration it might be, but [I]initialization[/I] is done within a pthread, or the main body of the program-which is a kind of thread itself I think.

Dang! I tried everydarnthing I could imagine. Read the instructions-my mother always told me that.

I think I've got an idea which will work for my purposes. To try it out, first I'm going to try modifying the code I posted earlier,to create two sets of otherwise identical lthreads-say serial numbers 0-19 from one pthread and 20-39 on a second pthread, and I'll have an lthread_signals_controls_lthreads() for each set, and inside the lthread_signals_controls_lthreads() I'll have it wait on a pthread_cond_t, sitting between lthread_compute_begin() and lthread_compute_end().

I'm psyched. Thanx. I'll post again, to give the results-if it works how I'm guessing, it'll be question answered.
 
Old 01-25-2017, 04:44 PM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by DeeDeeK View Post
I had overlooked that fact, that you can't invoke lthread calls from within the pthread which lthread_compute_begin() and lthread_compute_end()! Very obvious but I wasn't looking there.
Well, it's not that obvious. In fact, if it weren't for the fact that the github repo seems to be unmaintained, I would suggest reporting this as a documentation bug. You shouldn't have to go hunting to ferret out this kind of fundamental restriction from the docs.

Quote:
I was just imagining that a condition variable must be global-and I guess by declaration it might be, but initialization is done within a pthread, or the main body of the program-which is a kind of thread itself I think.
It's not just about the initialization, it's likely that the lthread functions simply don't perform the locking needed to provide thread safety.
 
1 members found this post helpful.
Old 01-27-2017, 09:05 PM   #7
DeeDeeK
Member
 
Registered: Jan 2016
Distribution: Ubuntu 14.04
Posts: 37

Original Poster
Rep: Reputation: Disabled
Quote:
Orig. posted by ntubski
Well, it's not that obvious. In fact, if it weren't for the fact that the github repo seems to be unmaintained, I would suggest reporting this as a documentation bug. You shouldn't have to go hunting to ferret out this kind of fundamental restriction from the docs.
Do you know of any currently maintained lightweight thread libraries which have lthread's sort of functionality? I really really really like the functions lthread_compute_begin() and lthread_compute_end()!

Being able to launch an lthread, then have it become nonblocking is so useful. I'd hate for this library to fade away without something similar to replace it. I'd like to learn enough to write my own, or be able to maintain it.

I was looking an GNU Pth, the GNU Portable Threads library, but it looks like it's been maybe ten years since it's been active?

I'm working on the code to synchronize several lthread schedulers using pthread condition variable signalling. I'll post it when it's working. I've had over 400 threads, each one managing a single sprite, animating it, doing collisions, and interacting with the others with an adapted version of Newtonian gravity, running quickly, all on one core. It is so easy to switch from using lthreads to pthreads, that I wrote it to use pthreads instead of lthreads if an evironmenta variable is set, and pthreads cannot begin to keep up. At 500 threads, pthreads is bogging down and lthreads is still reasonably quick. The difference is amazing.
 
Old 01-28-2017, 11:09 AM   #8
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by DeeDeeK View Post
Do you know of any currently maintained lightweight thread libraries which have lthread's sort of functionality? I really really really like the functions lthread_compute_begin() and lthread_compute_end()!

Being able to launch an lthread, then have it become nonblocking is so useful. I'd hate for this library to fade away without something similar to replace it. I'd like to learn enough to write my own, or be able to maintain it.
I don't know of any, but if you're really willing to maintain this one, you can try fixing things in your own fork and/or contact the author to get write access.
 
Old 01-29-2017, 09:44 AM   #9
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941
I think that there might be a fundamental mis-conception here about how lthreads ("lightweight threads") fundamentally differ from pthreads ("POSIX, i.e. operating-system, threads").

To quote the documentation:
Quote:
Originally Posted by http://lthread.readthedocs.io/en/latest/intro.html:
lthreads are created in userspace and don’t require kernel intervention, they are light weight and ideal for socket programming. Each lthread have separate stack, and the stack is madvise(2)-ed to save space, allowing you to create thousands(tested with a million lthreads) of coroutines and maintain a low memory footprint. The scheduler is hidden from the user and is created automagically in each pthread ...
Lightweight threads, of whatever flavor, are cooperatively multi-tasked. This is not an operating-system facility: it is a cooperative activity that requires a certain discipline from every lightweight-thread. The first diagram in the cited documentation shows how the lthread library wraps-up collections of lightweight-threads within an operating-system-dispatched pthread.

With such an arrangement I suggest that it should be "all or nothing." Either "do everything the lthread way, or don't do anything." This will be a lightweight and fast implementation of "co-routines" but it probably will not brook much interference from something else that is trying to use "pthreads" at the same time. Because it is not built by nor enforced by the operating system kernel, it is by architecture "somewhat fragile."

For instance, I would not attempt to use "operating-system 'condition variables'" at all in connection to such a library. I would not expect it to work. I would expect it to break things. If you cause the underlying pthread to be suspended, it cannot cooperatively dispatch any lightweight tasks.

Last edited by sundialsvcs; 01-29-2017 at 09:45 AM.
 
Old 01-30-2017, 05:58 PM   #10
DeeDeeK
Member
 
Registered: Jan 2016
Distribution: Ubuntu 14.04
Posts: 37

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by sundialsvcs View Post
For instance, I would not attempt to use "operating-system 'condition variables'" at all in connection to such a library. I would not expect it to work. I would expect it to break things. If you cause the underlying pthread to be suspended, it cannot cooperatively dispatch any lightweight tasks.
I've found that I can co-ordinate two sets of lightweight threads, each running on a different scheduler-and each scheduler is of course running in its own pthread. For each group of worker lthreads running on a scheduler, there is one more which uses the facility for not blocking other lthreads while making blocking calls, which the Lthreads library provides. So that one thread sits, waiting for that pthread_cond_t broadcast, and when it receives that broadcast, then makes an lthread_cond_broadcast call, to synchronize all the lthreads sharing its scheduler. No violation and no confusion.

It's important that lthreads be in user space and that it be separate but closely interoperating with pthreads, for this scheme to work. The trick is, in the middle of a lightweight thread, you can have nonblocking code-running on ANOTHER pthread-which you don't have to think about. Just call lthread_compute_begin() then write your otherwise blocking code, and after that blocking code is over, call lthread_compute_end(). SO, in the lthread which I have signal the other lthreads from, it actually blocks on that pthread_cond_t, but doesn't disrupt anything else.

So I can have several hundred or thousand lthreads running on one core, that many running on another - taking advantage of core associativity to keep a pthread running on a particular core - and an equal number of light weight threads running on another core, and then use pthread_cond_broadcast or pthread_cond_signal to let the two schedulers be in sync. I have it working already. It's hard to describe but wasn't hard to code. I should say coupled-not synced. My example makes no use of mutexs or semaphores, just kind of wings it.

I enjoy learning about abstract principles, coding conventions, and styles, but when it comes right down to it, I make my decisions based on the particulars of any new library or reimplementation of a library I'm already familiar with. I've been told so many times that one thing or another won't work on principle, but discovered that in fact it will.

here's a sloppy little example I wrote just to test the concept. I'm expanding on it. My idea is eventually to use on computer to display and use sockets to hook up several others, all running thousands of threads, to create some complex systems for, duh, complex systems studies. I want to be able to visualize the behavior, sort of an extreme version of the game of life, except with real complexity. For now I'm just using a little physics and silly graphics, and having fun with it. This isn't about tightly synchronized, highly coupled threads, and I think if you relax your concepts of what threads must and must not be, or what they can and can't be used for, you'll maybe see where I'm going with it.

For right now, it's more than fast enough for videogaming, at least 2d, with lots of animation and physics. My older test-of-concept where I had just one lthread scheduler is bouncing several hundred animated sprites around like it was nothing. And it's embarrassingly simple to switch from a lthreads to a pthreads paradigm. I just use a single environment variable as a flag.

But this example isn't of the sprites. It's fun to play with the timing and see the behavior changing.

I am using GCC 5.1.1 but this should work on earlier versions. I tend to use a cookie cutter to make my make files and I just cut and pasted. Probably no need for gnu11 or fms-extensions or -g -pg. I include two different gcc invocations. Both worked for me just fine to compile.

to compile:
Code:
gcc  --std=gnu11  -g -pg -fms-extensions -D_REENTRANT -pthread  -Wall multischedthreadx.c -o thxxc  -llthread `PKG_CONFIG_PATH=/usr/x86_64-linux-gnu;`
or maybe this will work for you:
Code:
gcc   -D_REENTRANT -pthread  -Wall multischedthreadx.c -o thxxc  -llthread `PKG_CONFIG_PATH=/usr/x86_64-linux-gnu;`

Code:
#include <lthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

typedef struct whatiam{
		int 						serialnumber;
		lthread_cond_t	**mysignal;
		int							*myinstructions;
		lthread_t				*my_lightweight_thread_variable;
} me_t;

typedef struct _signaller_info {
		int 						bottom;
		int							range;
		int							howmanyloops;
		lthread_cond_t  **mylthread_cond_variable;
		pthread_cond_t	*my_sync_signal;
} signaller_info;

int randquit;  //if nonzero lthreads will quit eventually at random with a 1/randquit chance

uint64_t syncfreq;

const int yes = 1,
	no = 0,
	quit = 1,
	cont = 0;
int set_to_quit_or_not = 0;

lthread_cond_t	*serialnumber_lthread_wakeup_signal,
									*thing_one, *thing_two;

pthread_cond_t 	dual_wakeup = PTHREAD_COND_INITIALIZER,
								thing1_wakeup = PTHREAD_COND_INITIALIZER,
								thing2_wakeup = PTHREAD_COND_INITIALIZER;
pthread_mutex_t likely_unused_mutex = PTHREAD_MUTEX_INITIALIZER;



int
intrand( int maximum ){
  if (!maximum)return 0;
  unsigned long intermediate = rand();
  intermediate *= (abs(maximum)+1);
  intermediate /= INT_MAX;
  return (int)intermediate;
}


void lthread_thread(void *who_I_am){
	me_t *myself = who_I_am;
	printf("\nnow in  lthread_thread  function...sn: %i\n", myself->serialnumber);
	for(;;){
		int report = lthread_cond_wait(*(myself->mysignal), intrand(33));
		if (!report){//return of zero means woke from the signal
			printf("sn:\t %i\treporting!\n", myself->serialnumber);
		}else if(report==-2){  //if timed out it reports -2
			if(set_to_quit_or_not == quit){
				printf("\nsn:\t %i\ttimed out and\tSIGNALLED TO QUIT!\n", myself->serialnumber);
				break;
			}else
				printf("sn:\t %i\t\ttimed out!!!\n", myself->serialnumber);
		}else{ // other return values not defined in the API
			printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~\nabnormal return from lthread_cond_wait\n~~~~~~~~~~~~~~~~~\n");
			break;
		}
		if((randquit)&&(intrand(randquit)>randquit-1)){ //random quitting helpful if no cond. signal is broadcast
			printf("\nserial number:\t %i\t\t\tQUITTING AT RANDOM!!!\n", 	myself->serialnumber);
			break;
		}
	}
	lthread_exit(NULL);
	return;
}

void lthread_signals_controls_lthreads(void *data){
	signaller_info *myinfo = data;
	printf("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nnow in lthread signaller thread, serving sn.s %i to %i\n", myinfo->bottom, myinfo->bottom+19);
	for(int i = 0; i < myinfo->howmanyloops; i++){
		/*between lthread_compute_begin() lthread_compute_end() we aren't blocking other lthreads*/
		lthread_compute_begin();
			usleep(syncfreq*100);
			printf("\nlthread signaller %i waiting on pthread_cond_wait\n", myinfo->bottom);
			pthread_cond_wait(myinfo->my_sync_signal, &likely_unused_mutex);
			printf("lthread signaller  %i waited on pthread_cond_wait\n", myinfo->bottom);
			if(set_to_quit_or_not == quit){
				printf("\n\nsignaller %i broadcasting for lthreads to quit\n\n", myinfo->bottom);
				/*we can compute_end because then we beak out of the loop with the other compute_end() */
				lthread_compute_end();
				break;
			}
		lthread_compute_end();
		printf("\n\nsignaller %i is now broadcasting for lthreads to report\n\n", myinfo->bottom);
		lthread_cond_broadcast(*myinfo->mylthread_cond_variable);
	}
	printf("\n\nsignaller %i broadcasting for lthreads to quit\n\n", myinfo->bottom);
	lthread_cond_broadcast(*myinfo->mylthread_cond_variable);
	printf("\n\nsignaller %i has finished broadcasting lthreads to quit\n\n", myinfo->bottom);
	usleep(80000);
	printf("\n\nsignaller %i now exiting\n\n", myinfo->bottom);
	lthread_exit((void*)myinfo->mylthread_cond_variable);
}

void *pthread_launches_lthreads(void *data){
	signaller_info *myinfo = data;
	lthread_cond_t *cond_variable;
	lthread_cond_create(&cond_variable);
	printf("\nnow in  pthread_launches_lthreads %i bottom\n", myinfo->bottom);

	for (int i = myinfo->bottom; i < myinfo->range+myinfo->bottom; i++){
		me_t *an_lthread_object = malloc(sizeof(me_t));
		an_lthread_object->serialnumber = i;
		an_lthread_object->myinstructions = &set_to_quit_or_not;
		an_lthread_object->mysignal = &cond_variable;
		lthread_create(&an_lthread_object->my_lightweight_thread_variable, lthread_thread, an_lthread_object);
		printf("\nnow in  pthread_launches %i bottom launching lthread\n", myinfo->bottom);
	}
	myinfo->mylthread_cond_variable = &cond_variable;
	lthread_t *an_lthread_signals;
	lthread_create(&an_lthread_signals, lthread_signals_controls_lthreads, (void*)myinfo);
	lthread_run();
	return NULL;
}

void*
two_lthread_scheduler_coordinator(void *data){
	pthread_t launchthread1,
						launchthread2;
	signaller_info *siginfdata = malloc(sizeof(signaller_info));
	set_to_quit_or_not = cont;

	printf("\nnow in two_lthread_scheduler_coordinator function\n");
	siginfdata->bottom = 0;
	siginfdata->range = 20;
	siginfdata->howmanyloops = 3000;
	siginfdata->my_sync_signal = &dual_wakeup;
	pthread_create(&launchthread1, NULL, pthread_launches_lthreads, (void*)siginfdata);
	siginfdata = malloc(sizeof(signaller_info));
	siginfdata->bottom = 21;
	siginfdata->range = 20;
	siginfdata->howmanyloops = 1000;
	siginfdata->my_sync_signal = &dual_wakeup;
	pthread_create(&launchthread2, NULL, pthread_launches_lthreads, (void*)siginfdata);
	int *cond_sig_frequency = data;
	for(;;){
		usleep(*cond_sig_frequency);
		pthread_cond_signal(&dual_wakeup);////pthread_cond_signal(&thing2_wakeup);
		if(intrand(10000) > 9999){
			set_to_quit_or_not = quit;
			printf("\n\n~~~~~~~~~~~~~~~~~~~~~~~~\n~~~~~~~~~~~~~~~~~~~~~\n~~~~~~~~~~~~~~~~~~~~~~~set quit signal-everyone should quit real real soon now\n");
			usleep(100000);
			break;
		}
	}
	return NULL;
}

int main(int argc, char **argv){


 	char *envvar = getenv("randquit");
	randquit = envvar ? atoi(envvar): no;

	envvar = getenv("syncfreq");
	syncfreq = envvar ? atoi(envvar): 200;

	two_lthread_scheduler_coordinator( (void*)&syncfreq);

	printf("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
	printf("\n please excuse sloppiness.\n setting syncfreq to something under 200 works well\non the computer this was written on\n\nset randquit and each thread has a 1/randquit chance of\nquiting each time it loops\n\n");
	printf("\n\nrandquit and synfreq are environmental variables\nenter randquit=[your number here] and hit return then enter export randquit\nsame for syncfreq\n");


	printf("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

	return 0;
}

Last edited by DeeDeeK; 01-30-2017 at 06:59 PM. Reason: Added a different command to compile
 
1 members found this post helpful.
Old 01-31-2017, 05:29 PM   #11
DeeDeeK
Member
 
Registered: Jan 2016
Distribution: Ubuntu 14.04
Posts: 37

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by ntubski View Post
... if you're really willing to maintain this one, you can try fixing things in your own fork and/or contact the author to get write access.
I am SO INTERESTED! A marvelous idea! It hadn't entered my mind but I really love this library, and feel that there is even more that could be done with it...But I am worried I might now be expert enough yet in C programming to do this.

I noticed that, obviously since I compiled it myself from source, I have the source code! Duh, yeah, but I am going to print it out on real paper so's I can mark it up by hand 'n stuff, and I am going to darn well learn enough that I could actually do just what you are suggesting!

I'm a little worried that the copyright holder won't be amenable, but then maybe he would. To have an active community maintaining it-even a community of two, himself and me for example-must carry some sort of hacker street-cred, don't you think?

What I would like to add are channels, bidirectional message passing channels between threads. Even between threads on different schedulers. If a thread can very simply pass a message to another thread, then that model could be abstracted and extended to use other means - even IPC, like sockets! This would make the kind of cross-core pthread/lthread synchronization attempted in the code I posted the other day irrelevant.

In my larger project, a specific instance of one of several structs holds data as well as functions which operate on that data, including its own thread. Sort of like a thread and sort of like an object. They don't have to be that way-I simply want it to be that way. It helps me to think of the problem that way.

These objects will represent actors in a complex system-like cellular automata but they aren't static, they move around and interact by contact or at a distance, as tho' through gravity or chemical signaling. Like bacteria or gravitating bodies do in the real world.

I was reading about the D language, which has messaging between threads, but I think I'd prefer to implement it myself, so I can control the details. After all, I started learning C because I'm creative and enjoy doing the work and getting my hands dirty.

Last edited by DeeDeeK; 01-31-2017 at 06:25 PM. Reason: too long. cutting it shorter
 
1 members found this post helpful.
Old 01-31-2017, 06:26 PM   #12
DeeDeeK
Member
 
Registered: Jan 2016
Distribution: Ubuntu 14.04
Posts: 37

Original Poster
Rep: Reputation: Disabled
https://www.cs.mtu.edu/~shene/NSF-3/...-overview.html

http://www.cs.mtu.edu/~shene/NSF-3/index.html

I just found this web page. Very intel--llesting.

It's supported by the National Science Foundation and has great tutorial stuffs

Last edited by DeeDeeK; 01-31-2017 at 06:31 PM.
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Bash to find all placeholder variables in a file and replace will real variables spadez Programming 6 11-26-2013 12:24 PM
check Negative egrep condition in an if condition novicunix Programming 5 02-02-2013 12:52 AM
what is the difference between -lpthread, -pthread, -lthread? nithima Linux - Newbie 2 03-31-2010 09:52 PM
Bash Script: parse active process stderr, strip, dump into variables, use variables TimeFade Programming 1 02-13-2010 06:09 AM
Condition Variables 2184ast Linux - General 0 02-21-2009 01:31 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:49 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration