POSIX: how to perform a context switch between threads? - linux-kernel

I want to implement the context switching between threads using Xilkernel, but there is no primitive POSIX-compliant that allows to stop and then resume the execution of a thread.
Is there anyone who can help me?

I do context switch for FPGA using this C code. If you find it useful and want ta get more of the surrounding code, just ask me.
/*
* threadswitch - change thread
*
* The thread stack-pointer is supplied as a parameter.
* The old thread's stack-pointer value is saved to the array
* thread_info_array, and a new thread is selected from the array.
* The stack pointer of the new thread is returned.
*/
unsigned int * threadswitch( unsigned int * old_sp )
{
unsigned int * new_sp;
number_of_thread_switches += 1; /* Increase thread-switch counter. */
/* Print line 1 of an informational message. */
printf( "\nPerforming thread-switch number %d. The system has been running for %d ticks.\n",
number_of_thread_switches,
get_internal_globaltime() );
/* Save the stack pointer of the old thread. */
thread_info_array[ currently_running_thread ].thread_sp = old_sp;
/* Print part 1 of a message saying which threads are involved this time. */
printf( "Switching from thread-ID %d ",
thread_info_array[ currently_running_thread ].thread_id );
/* Perform the scheduling decision (round-robin). */
currently_running_thread += 1;
if( currently_running_thread >= current_thread_count )
{
currently_running_thread = 0;
}
/* Print part 2 of the informational message. */
printf( "to thread-ID %d.\n",
thread_info_array[ currently_running_thread ].thread_id );
/* Get the stack pointer of the new thread. */
new_sp = thread_info_array[ currently_running_thread ].thread_sp;
/* Return. */
return( new_sp );
}

Related

Non-blockings reads/writes to stdin/stdout in C on Linux or Mac

I have two programs communicating via named pipes (on a Mac), but the buffer size of named pipes is too small. Program 1 writes 50K bytes to pipe 1 before reading pipe 2. Named pipes are 8K (on my system) so program 1 blocks until the data is consumed. Program 2 reads 20K bytes from pipe 1 and then writes 20K bytes to pipe2. Pipe2 can't hold 20K so program 2 now blocks. It will only be released when program 1 does its reads. But program 1 is blocked waiting for program 2. deadlock
I thought I could fix the problem by creating a gasket program that reads stdin non-blocking and writes stdout non-blocking, temporarily storing the data in a large buffer. I tested the program using cat data | ./gasket 0 | ./gasket 1 > out, expecting out to be a copy of data. However, while the first invocation of gasket works as expected, the read in the second program returns 0 before all the data is consumed and never returns anything other than 0 in follow on calls.
I tried the code below both on a MAC and Linux. Both behave the same. I've added logging so that I can see that the fread from the second invocation of gasket starts getting no data even though it has not read all the data written by the first invocation.
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 100000
char buffer[BUFFER_SIZE];
int elements=0;
int main(int argc, char **argv)
{
int total_read=0, total_write=0;
FILE *logfile=fopen(argv[1],"w");
int flags = fcntl(fileno(stdin), F_GETFL, 0);
fcntl(fileno(stdin), F_SETFL, flags | O_NONBLOCK);
flags = fcntl(fileno(stdout), F_GETFL, 0);
fcntl(fileno(stdout), F_SETFL, flags | O_NONBLOCK);
while (1) {
int num_read=0;
if (elements < (BUFFER_SIZE-1024)) { // space in buffer
num_read = fread(&buffer[elements], sizeof(char), 1024, stdin);
elements += num_read;
total_read += num_read;
fprintf(logfile,"read %d (%d) elements \n",num_read, total_read); fflush(logfile);
}
if (elements > 0) { // something in buffer that we can write
int num_written = fwrite(&buffer[0],sizeof(char),elements, stdout); fflush(stdout);
total_write += num_written;
fprintf(logfile,"wrote %d (%d) elements \n",num_written, total_write); fflush(logfile);
if (num_written > 0) { // copy data to top of buffer
for (int i=0; i<(elements-num_written); i++) {
buffer[i] = buffer[i+num_written];
}
elements -= num_written;
}
}
}
}
I guess I could make the gasket multi-threaded and use blocking reads in one thread and blocking writes in the other, but I would like to understand why non-blocking IO seems to break for me.
Thanks!
My general solution to any IPC project is to make the client and server non-blocking I/O. To do so requires queuing data both on writing and reading, to handle cases where the OS can't read/write, or can only read/write a portion of your message.
The code below will probably seem like EXTREME overkill, but if you get it working, you can use it the rest of your career, whether for named pipes, sockets, network, you name it.
In pseudo-code:
typedef struct {
const char* pcData, * pcToFree; // pcData may no longer point to malloc'd region
int iToSend;
} DataToSend_T;
queue of DataToSend_T qdts;
// Caller will use malloc() to allocate storage, and create the message in
// that buffer. MyWrite() will free it now, or WritableCB() will free it
// later. Either way, the app must NOT free it, and must not even refer to
// it again.
MyWrite( const char* pcData, int iToSend ) {
iSent = 0;
// Normally the OS will tell select() if the socket is writable, but if were hugely
// compute-bound, then it won't have a chance to. So let's call WritableCB() to
// send anything in our queue that is now sendable. We have to send the data in
// order, of course, so can't send the new data until the entire queue is done.
WritableCB();
if ( qdts has no entries ) {
iSent = write( pcData, iToSend );
// TODO: check error
// Did we send it all? We're done.
if ( iSent == iToSend ) {
free( pcData );
return;
}
}
// OK, either 1) we had stuff queued already meaning we can't send, or 2)
// we tried to send but couldn't send it all.
add to queue qdts the DataToSend ( pcData + iSent, pcData, iToSend - iSent );
}
WritableCB() {
while ( qdts has entries ) {
DataToSend_T* pdts = qdts head;
int iSent = write( pdts->cData, pdts->iToSend );
// TODO: check error
if ( iSent == pdts->iToSend ) {
free( pdts->pcToFree );
pop the front node off qdts
else {
pdts->pcData += iSent;
pdts->iToSend -= iSent;
return;
}
}
}
// Off-subject but I like a TINY buffer as an original value, that will always
// exercise the "buffer growth" code for almost all usage, so we're sure it works.
// If the initial buffer size is like 1M, and almost never grows, then the grow code
// may be buggy and we won't know until there's a crash years later.
int iBufSize = 1, iEnd = 0; iEnd is the first byte NOT in a message
char* pcBuf = malloc( iBufSize );
ReadableCB() {
// Keep reading the socket until there's no more data. Grow buffer if necessary.
while (1) {
int iRead = read( pcBuf + iEnd, iBufSize - iEnd);
// TODO: check error
iEnd += iRead;
// If we read less than we had space for, then read returned because this is
// all the available data, not because the buffer was too small.
if ( iRead < iBufSize - iEnd )
break;
// Otherwise, double the buffer and try reading some more.
iBufSize *= 2;
pcBuf = realloc( pcBuf, iBufSize );
}
iStart = 0;
while (1) {
if ( pcBuf[ iStart ] until iEnd-1 is less than a message ) {
// If our partial message isn't at the front of the buffer move it there.
if ( iStart ) {
memmove( pcBuf, pcBuf + iStart, iEnd - iStart );
iEnd -= iStart;
}
return;
}
// process a message, and advance iStart by the size of that message.
}
}
main() {
// Do your initial processing, and call MyWrite() to send and/or queue data.
while (1) {
select() // see man page
if ( the file handle is readable )
ReadableCB();
if ( the file handle is writable )
WritableCB();
if ( the file handle is in error )
// handle it;
if ( application is finished )
exit( EXIT_SUCCESS );
}
}

Read/Write from ATtiny1616 EEPROM

Using the ATting1616 within avr-gcc I am trying to read and write to the EEPROM.
The ATtiny1616 uses NVMCTRL - Nonvolatile Memory Controller for byte level read/writes. I am using NVMCTRL to read/write blocks from the EEPROM, but it is not working correctly.
Here is an example to demonstrate what I am trying to so.
Lets say that I was to save two different values within the EEPROM and then read back each ones value.
uint16_t eeprom_address1 = 0x01;//!< Address one for first saved value
uint16_t eeprom_address2 = 0x32;//!< Address two for second saved value
char save_one = "12345"; //!< Test value to save, one
char save_two = "testing";//!< Test value to save, two
FLASH_0_write_eeprom_block(eeprom_address1,save_one,7); //!< Save first value to address 1
FLASH_0_write_eeprom_block(eeprom_address2,save_two,7); //!< Save second value to address 2
char test_data[7] = {0}; //!< Just some empty array to put chars into
FLASH_0_read_eeprom_block(eeprom_address1,test_data,7); //!< Read eeprom from address, to address+ 7, and store back into test_data
Here are the read/write functions:
# define EEPROM_START (0x1400)//!< is located in header file
/**
* \brief Read a block from eeprom
*
* \param[in] eeprom_adr The byte-address in eeprom to read from
* \param[in] data Buffer to place read data into
*
* \return Nothing
*/
void FLASH_0_read_eeprom_block(eeprom_adr_t eeprom_adr, uint8_t *data, size_t size)
{
// Read operation will be stalled by hardware if any write is in progress
memcpy(data, (uint8_t *)(EEPROM_START + eeprom_adr), size);
}
/**
* \brief Write a block to eeprom
*
* \param[in] eeprom_adr The byte-address in eeprom to write to
* \param[in] data The buffer to write
*
* \return Status of write operation
*/
nvmctrl_status_t FLASH_0_write_eeprom_block(eeprom_adr_t eeprom_adr, uint8_t *data, size_t size)
{
uint8_t *write = (uint8_t *)(EEPROM_START + eeprom_adr);
/* Wait for completion of previous write */
while (NVMCTRL.STATUS & NVMCTRL_EEBUSY_bm)
;
/* Clear page buffer */
ccp_write_spm((void *)&NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEBUFCLR_gc);
do {
/* Write byte to page buffer */
*write++ = *data++;
size--;
// If we have filled an entire page or written last byte to a partially filled page
if ((((uintptr_t)write % EEPROM_PAGE_SIZE) == 0) || (size == 0)) {
/* Erase written part of page and program with desired value(s) */
ccp_write_spm((void *)&NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEERASEWRITE_gc);
}
} while (size != 0);
return NVM_OK;
}
The value that is turned if test_data[7] is printed will be "testing".
When looking at the memory in debug mode I am able to see that the value is always being written to the first memory location in the data EEPROM.[0x1400]
In this case starting at memory x1400 the value of "testing" starts.
There seems to be something fundamental that I have failed to understand with reading and write to the EEPROM. Any guidance would be greatly appreciated.

keyboard emulator device behavior on ubuntu

I'm building a device driver of sorts that consumes data from a keyboard emulating device.
The device is a card swipe, so its behavior is as follows:
User walks up, swipes card
I get a string of characters (key codes, really, including modifier keys for capital letters)
I don't know how many characters I'm going to get
I don't know when I'm getting something
Since I don't know how many characters I'm going to get, blocking reads on the keyboard tty aren't useful - I'd end up blocking after the last character. What I'm doing is, in Ruby, using the IO module to perform async reads against the keyboard device, and using a timeout to determine that the end of data was reached. This works fine logically (even a user swiping his or her card fast will do so slower than the send rate between characters).
The issue is that sometimes, I lose data from the middle of the string. My hunch is that there's some sort of buffer overflow happening because I'm reading the data too slowly. Trying to confirm this, I inserted small waits in between each key process. Longer waits (20ms+) do exacerbate the problem. However, a wait of around 5ms actually makes it go away? The only explanation I can come up with is that the async read itself is expensive (because Ruby), and doing them without a rate limit is actually slower than doing them with a 5ms delay.
Does this sound rational? Are there other ideas on what this could be?
The ruby is actually JRuby 9000. The machine is Ubuntu LTS 16.
Edit: here's a snippet of the relevant code
private def read_swipe(buffer_size, card_reader_input, pause_between_reads, seconds_to_complete)
limit = Time.now + seconds_to_complete.seconds
swipe_data = ''
begin
start_time = Time.now
sleep pause_between_reads
batch = card_reader_input.read_nonblock(buffer_size)
swipe_data << batch
rescue IO::WaitReadable
IO.select([card_reader_input], nil, nil, 0.5)
retry unless limit < start_time
end while start_time < limit
swipe_data
end
where card_reader_input = File.new(event_handle, 'rb')
I am not sure about Ruby code but you can use linux sysfs to access the characters coming out of keyboard 'like' device, and if feasible you can call C code from ruby application. I had done this for barcode reader and following is the code:
static int init_barcode_com(char* bcr_portname)
{
int fd;
/* Open the file descriptor in non-blocking mode */
fd = open(bcr_portname, O_RDONLY | O_NOCTTY | O_NDELAY);
cout << "Barcode Reader FD: " << fd <<endl;
if (fd == -1)
{
cerr << "ERROR: Cannot open fd for barcode communication with error " << fd <<endl;
}
fcntl(fd, F_SETFL, 0);
/* Set up the control structure */
struct termios toptions;
/* Get currently set options for the tty */
tcgetattr(fd, &toptions);
/* Set custom options */
/* 9600 baud */
cfsetispeed(&toptions, B9600);
cfsetospeed(&toptions, B9600);
/* 8 bits, no parity, no stop bits */
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
/* no hardware flow control */
toptions.c_cflag &= ~CRTSCTS;
/* enable receiver, ignore status lines */
toptions.c_cflag |= CREAD | CLOCAL;
/* disable input/output flow control, disable restart chars */
toptions.c_iflag &= ~(IXON | IXOFF | IXANY);
/* disable canonical input, disable echo,
* disable visually erase chars,
* disable terminal-generated signals */
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/* disable output processing */
toptions.c_oflag &= ~OPOST;
/* wait for n (in our case its 1) characters to come in before read returns */
/* WARNING! THIS CAUSES THE read() TO BLOCK UNTIL ALL */
/* CHARACTERS HAVE COME IN! */
toptions.c_cc[VMIN] = 0;
/* no minimum time to wait before read returns */
toptions.c_cc[VTIME] = 100;
/* commit the options */
tcsetattr(fd, TCSANOW, &toptions);
/* Wait for the Barcode to reset */
usleep(10*1000);
return fd;
}
static int read_from_barcode_reader(int fd, char* bcr_buf)
{
int i = 0, nbytes = 0;
char buf[1];
/* Flush anything already in the serial buffer */
tcflush(fd, TCIFLUSH);
while (1) {
nbytes = read(fd, buf, 1); // read a char at a time
if (nbytes == -1) {
return -1; // Couldn't read
}
if (nbytes == 0) {
return 0;
}
if (buf[0] == '\n' || buf[0] == '\r') {
return 0;
}
bcr_buf[i] = buf[0];
i++;
}
return 0;
}
Now that you do not know how many characters your going to get you can use VMIN and VTIME combination to address your concern. This document details various possibilities with VMIN and VTIME.

SIM900: How to be sure how much time to wait between serial(UART) transmit and receive

i have written a library in C for using the SIM900 GSM with my uC but it has many many bugs. Sometimes it works sometimes not. My hardware works fine I think.
I rewrote it and made sure that the basic functions are bug free.
SIM900_transmit( char* );
SIM900_reveive( char** );
SIM900_on();
SIM900_off();
Now I want to write the SIM900_command function that will use SIM900_transmit( char* ) and SIM900_reveive( char** );
So my detailed question is:
How to know how much time to wait between AT command and receiving the answer from SIM900. I do not want to just put _delay_ms(1000).
Thanks in advance...
Usually, you wait until a character is available and then receive it. Have a look here. There you have for AVR devices with a single UART:
unsigned char uart_recieve (void)
{
while(!(UCSRA) & (1<<RXC));
return UDR;
}
So, with while(!(UCSRA) & (1<<RXC)); you basically block execution until there is a character available at the uart.
I found my main problem. Now I will fix the old SIM900 library.
OLD CODE:
/*
* Sent the AT command.
*/
softuart_puts_P( "Transmit" );
SIM900_transmit( "AT\r" );
softuart_puts_P( " completed\r\n" );
/*
* Wait until SIM900 answers back.
*/
while ( uart_available() == 0 )//BUG: Loop in a loop(receive has one) caused chaos.
{
/*
* Sent the AT command.
*/
softuart_puts_P( "Received: [" );
cString answer = newEmptyString();
SIM900_receive( &answer );
softuart_puts( answer );
softuart_puts_P( "]\r\n" );
deleteString( &answer );
}
NEW CODE
/*
* Sent the AT command.
*/
softuart_puts_P( "Transmit" );
SIM900_transmit( "AT\r" );
softuart_puts_P( " completed\r\n" );
/*
* Wait until SIM900 answers back.
*/
while ( uart_available() == 0 );// TODO: Put timeout in case SIM900 is switched off.
/*
* Sent the AT command.
*/
softuart_puts_P( "Received: [" );
cString answer = newEmptyString();
SIM900_receive( &answer );
softuart_puts( answer );
softuart_puts_P( "]\r\n" );
deleteString( &answer );
This does the work: while ( uart_available() == 0 );
Thanks for your help.

How do I get an Mac OS Component Manager Component to be visible to other processes?

This is a bit esoteric, but there have to be a few people here who know how OS X's Carbon Component Manager works. I've made a couple of little apps to play around with making Components (see here for some background). Actually, one of the apps is a sample program straight from Apple called 'Fiendishthngs'. It lists all the Components that the Component Manager is making available. My program is a simple little thing that registers a Component, lists all the Components that the Component Manager has, and then waits around indefinately (to avoid purging the Component that it registered).
On my system, the Component Manager is tracking 873 Components (mostly codecs of one sort of another). My program that registers a Component registers it, and then counts 874 Components because it just registered one itself, of course). Here's the source:
void RegisterBasicComponent()
{
ComponentDescription desc;
desc.componentType = kMyComponentType;
desc.componentSubType = kMyComponentSubType;
desc.componentManufacturer = kMyComponentManufacturer;
desc.componentFlags = 0;
desc.componentFlagsMask = cmpIsMissing;
ComponentRoutineUPP MyComponentRoutineUPP
= NewComponentRoutineUPP( &MyComponentRoutineProc );
// Handle name_handle = NewHandle( sizeof( kMyComponentName ) );
//strcpy( *(char**)name_handle, kMyComponentName );
//RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, name_handle, NULL, NULL );
Component component = RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, NULL, NULL, NULL );
if ( NULL != component )
printf("The registration seems to have worked!\n");
else
printf("Nope - didn't work for some reason.\n");
}
int main( void )
{
RegisterBasicComponent();
ComponentDescription looking;
// OSType componentType; /* A unique 4-byte code indentifying the command set */
// OSType componentSubType; /* Particular flavor of this instance */
// OSType componentManufacturer; /* Vendor indentification */
// UInt32 componentFlags; /* 8 each for Component,Type,SubType,Manuf/revision */
// UInt32 componentFlagsMask; /* Mask for specifying which flags to consider in search, zero during registration */
looking.componentType = kAnyComponentType;
looking.componentSubType = kAnyComponentSubType;
// looking.componentSubType = kComponentResourceType
looking.componentManufacturer = kAnyComponentManufacturer;
looking.componentFlags = 0;
looking.componentFlagsMask = cmpIsMissing;
long numComponents = CountComponents ( &looking );
printf("Found %ld components.\n", numComponents);
Component component = 0;
int i = 0;
while (true)
{
component = FindNextComponent(component, &looking);
if ( 0 == component )
break;
ComponentDescription desc;
Handle componentName = NewHandle(256);
Handle componentInfo = NewHandle(1024);
Handle componentIcon = 0;
OSErr err = GetComponentInfo( component,
&desc,
componentName,
componentInfo,
componentIcon );
if ( err != noErr )
{
printf("Couldn't find any info on component %d of %ld in list!\n", i
, numComponents);
break;
}
printf( "%d of %ld: '%c%c%c%c', '%c%c%c%c', '%c%c%c%c', '%s'\n",
i, numComponents,
SPLAT_WORD( desc.componentManufacturer ),
SPLAT_WORD( desc.componentType ),
SPLAT_WORD( desc.componentSubType ),
*componentName );
RecoverHandle( *componentName );
RecoverHandle( *componentInfo );
++i;
}
while (true)
{
printf("Waiting around for someone to use me...\n");
sleep( 3 );
}
}
Anyways, when I run this, keep it running (so the Component would presumably stay registered with the Component Manager), and then run Fiendishthngs, Fiendishthngs can't see my test Component that I register - it only sees 873 Components. The 'registerComponentGlobal' flag passed into RegisterComponent() is supposed to make the Component available to other processes, but it seems like something is going awry.
Any ideas?
Well, I left this issue behind, resigning myself to the fact that OS X's Component Manager probably doesn't support the 'global' option anymore.
This would make a lot of sense, really. Making your component 'global' from your process to other processes would require out-of-process call marshalling, like with RPC, with OS X. On the other hand, in OS 9 and earlier, it would make perfect sense, given that all processes lived in a common address space. For OS 9 it would be trivial to make a component globally available to all processes.
Anyways, today I was disassembling RegisterComponentFileRefEntries() where the relevant code seems to reside, and sure enough, I saw this in the pre-amble to the function (the comments are mine):
0x9841a026 <+0018> mov eax, DWORD PTR [ebp+0x8] // load param spec
0x9841a029 <+0021> mov DWORD PTR [ebp-0xdc],eax // local spec = param spec
0x9841a02f <+0027> mov edx,DWORD PTR [ebp+0x10] // load param toRegister
0x9841a032 <+0030> mov DWORD PTR [ebp-0xe0],edx // local toRegister = param toRegister
The signature for RegisterComponentFileRefEntries is
extern OSErr
RegisterComponentFileEntries(
const FSSpec * spec,
short global,
const ComponentDescription * toRegister, /* can be NULL */
UInt32 registerCount)
The only 2 parameters that RegisterComponentFileRefEntries bothers with are spec (at ebp+0x8) and toRegister (at ebp+0x10). global (at ebp+0xc) and registerCount (at ebp+0x14) are completely ignored.

Resources