I have this code like this:
uint16_t getNextAvailableTransactionID() throw (RMAPEngineException) {
transactionIDMutex.lock();
if (availableTransactionIDList.size() != 0) {
unsigned int tid = *(availableTransactionIDList.begin());
availableTransactionIDList.pop_front();
transactionIDMutex.unlock();
return tid;
} else {
transactionIDMutex.unlock();
throw RMAPEngineException(RMAPEngineException::TooManyConcurrentTransactions);
}
}
and the availableTransactionIDList is a std::list of C++
Because I use this function as a part in reading out data from hardware. After checking, the overhead coming from the the availableTransactionIDList (I used a clock_gettime() and make a timestamp in the functions to check).
Just wondering, is there anyway to solve the problem with overhead of std::list ?
Related
I have the following kernel module probe function (simplified to show the relevant parts):
static int qnap_ec_probe(struct platform_device* platform_dev)
{
// Allocate memory for the custom data and associate with the device
struct qnap_ec_platform_drv_data* platform_drv_data;
platform_drv_data = devm_kzalloc(&platform_dev->dev, sizeof(struct qnap_ec_platform_drv_data),
GFP_KERNEL);
// Add the custom data to the platform device
platform_set_drvdata(platform_dev, platform_drv_data);
// Register the platform device
devm_hwmon_device_register_with_info(&platform_dev->dev, "qnap_ec", NULL,
&qnap_ec_hwmon_chip_info, NULL);
return 0;
}
and the following hwmon read callback function:
static int qnap_ec_hwmon_read(struct device* dev, enum hwmon_sensor_types type, u32 attribute,
int channel, long* value)
{
struct qnap_ec_platform_drv_data* platform_drv_data;
platform_drv_data = dev_get_drvdata(dev);
if (platform_drv_data == NULL)
{
return -1;
}
return 0;
}
Unfortunately the second function always returns -1 because the dev_get_drvdata function always returns NULL. For some reason the data that's associated with the device in the probe function using platform_set_drvdata doesn't make it into the hwmon read callback function. Am I missing a step in associating this data with the device? What could be causing this issue?
Hello Dear participants of stackoverflow,
I'm new to kernel space development and still in the beginning of the road.
I developed a basic char device driver that can read open close etc . But couldn't find a proper source and how to tutorial for Poll/select mechanism sample.
I've written the sample code for poll function below:
static unsigned int dev_poll(struct file * file, poll_table *wait)
{
poll_wait(file,&dev_wait,wait);
if (size_of_message > 0 ){
printk(KERN_INFO "size_of_message > 0 returning POLLIN | POLLRDNORM\n");
return POLLIN | POLLRDNORM;
}
else {
printk(KERN_INFO "dev_poll return 0\n");
return 0;
}
}
It works fine but couldn't undestand a few things.
When I call select from user space program as
struct timeval time = {5,0 } ;
select(fd + 1 , &readfs,NULL,NULL,&time);
the dev_poll function in driver called once and return zero or POLLIN in order to buffer size . And then never called again. In user space , after 5 seconds the program continue if dev_poll returned 0.
What I couldn't understand is here , How the driver code will decide and let user space program if there is something in buffer that is readable withing this 5 seconds , if it's called once and returned immediately.
Is there anyway in kernel module to gather information of timeval parameter that comes from userspace ?
Thank you from now on.
Regards,
Call poll_wait() actually places some wait object into a waitqueue, specified as a second parameter. When wait object is fired (via waitqueue's wake_up or similar function), the poll function is evaluated again.
Kernel driver needn't to bother about timeouts: when time is out, the wait object will be removed from the waitqueue automatically.
Hello dear curious people like me about poll . I came up with a solution.
From another topic on stackowerflow a guy said that the poll_function is called multiple times if kernel need to last situation. So basically I implement that code .
when poll called call wait_poll(wait_queue_head);
when device have buffered data(this is usually in driver write function).
call wake_up macro with wait_queue_head paramater.
So after this step poll function of driver is called again .
So here you can return whatever you want to return. In this case POLLIN | POLLRDNORM..
Here is my sample code for write and poll in the driver.
static unsigned int dev_poll(struct file * file, poll_table *wait)
{
static int dev_poll_called_count = 0 ;
dev_poll_called_count ++;
poll_wait(file,&dev_wait,wait);
read_wait_queue_length++;
printk(KERN_INFO "Inside dev_poll called time is : %d read_wait_queue_length %d\n",dev_poll_called_count,read_wait_queue_length);
printk(KERN_INFO "After poll_wait wake_up called\n");
if (size_of_message > 0 ){
printk(KERN_INFO "size_of_message > 0 returning POLLIN | POLLRDNORM\n");
return POLLIN | POLLRDNORM;
}
else {
printk(KERN_INFO "dev_poll return 0\n");
return 0;
}
}
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
printk(KERN_INFO "Inside write \n");;
int ret;
ret = copy_from_user(message, buffer, len);
size_of_message = len ;
printk(KERN_INFO "EBBChar: Received %zu characters from the user\n", size_of_message);
if (ret)
return -EFAULT;
message[len] = '\0';
printk(KERN_INFO "gelen string %s", message);
if (read_wait_queue_length)
{
wake_up(&dev_wait);
read_wait_queue_length = 0;
}
return len;
}
I am attempting to send data from device to host using the Gazelle protocol, however, when reading a time varying signal in on MATLAB the values continuously change elements in the array.
Here is the Simblee/Rfduino host code:
#include <SimbleeGZLL.h>
device_t role = HOST;
char array[5];
void setup() {
Serial.begin(9600);
SimbleeGZLL.begin(role);
timer_one(1); // 1 ms timer
}
void loop() {
Serial.flush();
printf(EMG);
}
void SimbleeGZLL_onReceive(device_t device, int rssi, char *data, int len)
{
if (len > 0) {
digitalWrite(2,HIGH);
array[0] = data[0];
array[1] = data[1];
array[2] = data[2];
array[3] = data[3];
array[4] = '\0';
} else SimbleeGZLL.sendToDevice(device, 'A');
}
And the device code:
include
device_t role = DEVICE1;
volatile int state;
char array[4];
void setup() {
SimbleeGZLL.begin(role);
Serial.begin(9600);
timer_one(1);
}
void loop() {
array[0] = analogRead(2);
array[1] = analogRead(3);
array[2] = analogRead(4);
array[3] = analogRead(5);
SimbleeGZLL.sendToHost(EMG,4);
}
Could someone please provide some assistance to identify where the issue may lie?
Thank you!
Matlab is not super reliable with serial communication. I actually had a similar issue with a serial device where the input values would be out of order. Are you signaling when to start and stop printing? What does your matlab code look like?
I would set up a ring buffer on the host and the device to deal with the asycn time issues.
You are going to get timing issues with the current method. What kind of frequency are you going for? The analogRead is super slow, and double multiple in a row seems to make things even slower. Could you try to set up an ADC interrupt?
Where is your timer code?
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/sem.h>
#include<sys/ipc.h>
int sem_id;
void update_file(int number)
{
struct sembuf sem_op;
FILE* file;
printf("Inside Update Process\n");
/* wait on the semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1; /* <-- Amount by which the value of the semaphore is to be decreased */
sem_op.sem_flg = 0;
semop(sem_id, &sem_op, 1);
/* we "locked" the semaphore, and are assured exclusive access to file. */
/* manipulate the file in some way. for example, write a number into it. */
file = fopen("file.txt", "a+");
if (file) {
fprintf(file, " \n%d\n", number);
fclose(file);
}
/* finally, signal the semaphore - increase its value by one. */
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop( sem_id, &sem_op, 1);
}
void write_file(char* contents)
{
printf("Inside Write Process\n");
struct sembuf sem_op;
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop( sem_id, &sem_op, 1);
FILE *file = fopen("file.txt","w");
if(file)
{
fprintf(file,contents);
fclose(file);
}
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop( sem_id, &sem_op, 1);
}
int main()
{
//key_t key = ftok("file.txt",'E');
sem_id = semget( IPC_PRIVATE, 1, 0600 | IPC_CREAT);
/*here 100 is any arbit number to be assigned as the key of the
semaphore,1 is the number of semaphores in the semaphore set, */
if(sem_id == -1)
{
perror("main : semget");
exit(1);
}
int rc = semctl( sem_id, 0, SETVAL, 1);
pid_t u = fork();
if(u == 0)
{
update_file(100);
exit(0);
}
else
{
wait();
}
pid_t w = fork();
if(w == 0)
{
write_file("Hello!!");
exit(0);
}
else
{
wait();
}
}
If I run the above code as a c code, the write_file() function is called after the update_file () function
Whereas if I run the same code as a c++ code, the order of execution is reverse... why is it so??
Just some suggestions, but it looks to me like it could be caused by a combination of things:
The wait() call is supposed to take a pointer argument (that can
be NULL). Compiler should have caught this, but you must be picking
up another definition somewhere that permits your syntax. You are
also missing an include for sys/wait.h. This might be why the
compiler isn't complaining as I'd expect it to.
Depending on your machine/OS configuration the fork'd process may
not get to run until after the parent yields. Assuming the "wait()"
you are calling isn't working the way we would be expecting, it is
possible for the parent to execute completely before the children
get to run.
Unfortunately, I wasn't able to duplicate the same temporal behavior. However, when I generated assembly files for each of the two cases (C & C++), I noticed that the C++ version is missing the "wait" system call, but the C version is as I would expect. To me, this suggests that somewhere in the C++ headers this special version without an argument is being #defined out of the code. This difference could be the reason behind the behavior you are seeing.
In a nutshell... add the #include, and change your wait calls to "wait(0)"
Hi i am trying to do packet injection using raw sockets, i have a problem in getting the interface index using SIOCGIFINDEX command of the ioctl. I am using ubuntu 12.04 as my OS. Please help the code is:
int BindRawSocketToInterface(char *device, int rawsock, int protocol)
{
struct sockaddr_ll sll;
struct ifreq ifr;
bzero(&sll, sizeof(sll));
bzero(&ifr, sizeof(ifr));
/* First Get the Interface Index */
strncpy ((char*) ifr.ifr_name, device, IFNAMSIZ);
if ((ioctl(rawsock, SIOCGIFINDEX, &ifr))== -1)
{
printf ("Error getting interface index!\n");
exit(-1);
}
/* Bind our rawsocket to this interface */
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(protocol);
if ((bind(rawsock, (struct sockaddr*)&sll,sizeof(sll)))== -1)
{
perror("Error binding raw socket to interface \n");
exit(-1);
}
return 1;
}
Here is an example:
http://austinmarton.wordpress.com/2011/09/14/sending-raw-ethernet-packets-from-a-specific-interface-in-c-on-linux/
I hope this helps
As a reminder for anyone searching for such a function, i've seen many variants of this function and many of them have the following bug, so its probably a copy paste bug to be warned of:
strncpy ((char*) ifr.ifr_name, device, IFNAMSIZ);
This line has an OBOE (off-by-one error) and an unnecessary cast to char *.
strncpy (ifr.ifr_name, device, sizeof ifr.ifr_name - 1);
should be used instead.