I have recently found this prototype for the sched_setaffinity method:
extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
I am attempting to use this to set the affinity of a task but it doesn't seem to be working. This is my implementation:
#define _GNU_SOURCE
#include <linux/sched.h>
#include <linux/cpumask.h>
int set_aff (pid_t pid, int core)
{
static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS);
struct cpumask *const task_cpumask = to_cpumask(cpu_possible_bits);
cpumask_set_cpu(core, task_cpumask);
sched_setaffinity(pid, task_cpumask);
return 0;
}
My code compiles without any errors however when I try to call this method, it breaks. Does anyone know why?
Is there a better way to do this from inside a kernel method?
You should try this:
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(1, &cpuset);
if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset))
exit(1);
Related
[skip to UPDATE2 and save some time :-)]
I use ARM Cortex-M4, with CMSIS 5-5.7.0 and FreeRTOS, compiling using GCC for ARM (10_2021.10)
My variables are not initialized as they should.
My startup code is pretty simple, the entry point is the reset handler (CMSIS declared startup_ARMCM4.s as deprecated and recommend using the C code startup code so this is what I do).
Here is my code:
__attribute__((__noreturn__)) void Reset_Handler(void)
{
DataInit();
SystemInit(); /* CMSIS System Initialization */
main();
}
static void DataInit(void)
{
typedef struct {
uint32_t const* src;
uint32_t* dest;
uint32_t wlen;
} __copy_table_t;
typedef struct {
uint32_t* dest;
uint32_t wlen;
} __zero_table_t;
extern const __copy_table_t __copy_table_start__;
extern const __copy_table_t __copy_table_end__;
extern const __zero_table_t __zero_table_start__;
extern const __zero_table_t __zero_table_end__;
for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) {
for(uint32_t i=0u; i<pTable->wlen; ++i) {
pTable->dest[i] = pTable->src[i];
}
}
for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
for(uint32_t i=0u; i<pTable->wlen; ++i) {
pTable->dest[i] = 0u;
}
}
}
__copy_table_start__, __copy_table_end__ etc. have the wrong values an so no data is copied to the appropriate place in RAM.
I tried adding __libc_init_array() before DataInit(), as suggested in this answer, and remove the nostartfiles flag from the linker, but at some point __libc_init_array() jumps to an illegal address and I get a HardFault interrupt.
Is there a different method to fix it? maybe one where I can use the nostartfiles flag?
UPDATE:
Looking at the memory, where __copy_table_start__ is located, I see the data there is valid (even without the use of __libc_init_array()). It seems that pTable doesn't get the correct value.
I tried using __data_start__, __data_end__, __bss_start__, __bss_end__ and __etext instead of the above variables, in the linker file it is said they can be used in code without definition, but they cannot (maybe that's a clue?). In any case they didn't work either.
UPDATE2:
found the actual problem
all struct members get the same value (modifying one changes all others), it happens with every struct. I have no idea how this is possible. In other words the value of __copy_table_start__.src is, for example, 0x14651234, __copy_table_start__.dest is 0x00100000, and __copy_table_start__.wlen is 0x0365. When looking at pTable all members are 0x14651234.
I am trying to access super block object which is defined in linux/fs.h.
But how to initialize the object so that we can access it's properties.
I found that alloc_super() is used to initialize super but how is it called?
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <linux/fs.h>
int main(){
printf("hello there");
struct super_block *sb;
return 0;
}
The answer is very much file system dependent, since different file systems will have different super block layouts and infact different arrangements of blocks.
For instance, ext2 file systems superblock is in a known location on disk (byte 1024), and has a known size (sizeof(struct superblock) bytes).
So a typical implementation (This is not a working code but with minor modification can be made to work ) of what you want would be:
struct superblock *read_superblock(int fd) {
struct superblock *sb = malloc(sizeof(struct superblock));
assert(sb != NULL);
lseek(fd, (off_t) 1024, SEEK_SET));
read(fd, (void *) sb, sizeof(struct superblock));
return sb;
}
Now, you can alloc superblock using linux/headers, or write your own struct that exactly matches with the ext2/ext3/etc/etc file systems superblock.
Then you must know where to find the superblock (the lseek() comes here).
Also you need to pass the disk file name file_descriptor to the function.
So do a
int fd = open(argv[1], O_RDONLY);
struct superblock * sb = read_superblock(fd);
I have 4 different depth cameras available to me: Kinect, Xtion, PMD nano, Softkinetic DepthSense.
I have the libraries that know how to read all of them: OpenNI, PMD drivers, Softkinetic drivers.
I would ideally like to make a simple grabber for each kind of camera and then just use it as a plugin into any other program i.e. get fast, non redundant access (i.e. not too many memory copies) to the data stream.
One of the problems is that in many cases I dont have the right library in 32 or 64 bit so I cant compile all grabbers in the same project.
What is the best way to achieve this?
I am a researcher so this idea isnt necessarily useful for production code but given this scenario my best solution has been to create a server process for each type of camera. Each server process knows how to load its own type of camera stream and then throws it into a shared memory space that other processes can read from.
It is obviously possible to use different kind of locking mechanisms but I have left the below code without any locks.
The server process will include the following:
#define BOOST_ALL_NO_LIB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
using namespace std;
using namespace boost::interprocess;
struct sharedImage
{
enum { width = 320 };
enum { height = 240 };
enum { dataLength = width*height*sizeof(unsigned short) };
sharedImage(){}
interprocess_mutex mutex;
unsigned short data[dataLength];
};
shared_memory_object shm;
sharedImage * sIm;
mapped_region region;
int setupSharedMemory(){
// Clear the object if it exists
shared_memory_object::remove("ImageMem");
shm = shared_memory_object(create_only /*only create*/,"ImageMem" /*name*/,read_write/*read-write mode*/);
printf("Size:%i\n",sizeof(sharedImage));
//Set size
shm.truncate(sizeof(sharedImage));
//Map the whole shared memory in this process
region = mapped_region(shm, read_write);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in the preallocated memory of shm
sIm = new (addr) sharedImage;
return 0;
}
int shutdownSharedMemory(){
shared_memory_object::remove("ImageMem");
return 0;
}
To start it up call setupSharedMemory() and to shut down call shutdownSharedMemory().
All the values are hard coded in this simple example but its easy to imagine making it more flexible.
Now lets assume that you are using SoftKinetic's DepthSense. So then you could write the following callback for the Depth node.
void onNewDepthSample(DepthNode node, DepthNode::NewSampleReceivedData data) {
//scoped_lock<interprocess_mutex> lock(sIm->mutex);
memcpy(sIm->data, data.depthMap, sIm->dataLength);
}
What this does is simply copies the latest depth map into the shared memory space.
You could also add a timestamp and a lock and anything else you need but this basic code works well enough for me so I will leave it as it is.
Now in some other process you can access the data in a very similar fashion.
The code below is what I use to get the live SoftKinetic DepthSense depth stream into Matlab for real time processing. This method has a huge advantage over trying to write my own mex wrapper specifically for SoftKinetic because I can use the same code for all the other cameras if I write servers for them.
#include <math.h>
#include <windows.h>
#include "mex.h"
#define BOOST_ALL_NO_LIB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace boost::interprocess;
struct sharedImage
{
enum { width = 320 };
enum { height = 240 };
enum { dataLength = width*height*sizeof(short) };
sharedImage(): dirty(true){}
interprocess_mutex mutex;
uint8_t data[dataLength];
bool dirty;
};
void getFrame(unsigned short *D)
{
//Open the shared memory object.
shared_memory_object shm(open_only ,"ImageMem", read_write);
//Map the whole shared memory in this process
mapped_region region(shm ,read_write);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
sharedImage * sIm = static_cast<sharedImage*>(addr);
//scoped_lock<interprocess_mutex> lock(sIm->mutex);
memcpy((char*)D, (char*)sIm->data, sIm->dataLength);
}
void mexFunction(int nlhs, mxArray *plhs[ ], int nrhs, const mxArray *prhs[ ])
{
// Build outputs
mwSize dims[2] = {320, 240};
plhs[0] = mxCreateNumericArray(2, dims, mxUINT16_CLASS, mxREAL);
unsigned short *D = (unsigned short*)mxGetData(plhs[0]);
try
{
getFrame(D);
}
catch (interprocess_exception &ex)
{
mexPrintf("getFrame:%s\n", ex.what());
}
}
which on my computer I compile in Matlab with: mex getSKFrame.cpp -IC:\Development\boost_1_48_0
And then finally to use it in Matlab: D = getSKFrame()'; imagesc(D)
Thank you for looking at this post. I am trying to patch up a network block device driver. If you need to see the sources they are at http : / / code.ximeta.com.
I noticed that lock_kernel() seems deprecated as of linux 2.6.37. I read "The new way of ioctl()" and found that device drivers now should perform a specific lock before operating.
So I would like some advice replacing this if possible.
I have found two sections in the current code that I think are related, in the block folder section.
Source
block->io.c
->ctrldev.c
I put snippets from each for your consideration.
io.c contains one call to lock_kernel:
NDAS_SAL_API xbool sal_file_get_size(sal_file file, xuint64* size)
{
definitions and declarations etc..
lock_kernel();
#ifdef HAVE_UNLOCKED_IOCTL
if (filp->f_op->unlocked_ioctl) {
some small statements
error = filp->f_op->unlocked_ioctl(filp, BLKGETSIZE64, (unsigned long)size);
actions if error or not etc.
}
#endif
unlock_kernel();
return ret;
}
And ctrldev.c contains the main io function:
#include <linux/spinlock.h> // spinklock_t
#include <linux/semaphore.h> // struct semaphore
#include <asm/atomic.h> // atomic
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/ide.h>
#include <linux/smp_lock.h>
#include <linux/time.h>
......
int ndas_ctrldev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
lots of operations and functions.
return result;
}
Later ndas_ctrldev_ioctl function is set as the former .ioctl.
static struct file_operations ndasctrl_fops = {
.write = ndas_ctrldev_write,
.read = ndas_ctrldev_read,
.open = ndas_ctrldev_open,
.release = ndas_ctrldev_release,
.ioctl = ndas_ctrldev_ioctl,
};
Now I want to convert this to avoid using lock_kernel();
According to my understanding I will modified the former sections as below:
NDAS_SAL_API xbool sal_file_get_size(sal_file file, xuint64* size)
{
definitions and declarations etc..
#ifndef HAVE_UNLOCKED_IOCTL
lock_kernel();
#endif
#ifdef HAVE_UNLOCKED_IOCTL
if (filp->f_op->unlocked_ioctl) {
some small statements
error = filp->f_op->unlocked_ioctl(filp, BLKGETSIZE64, (unsigned long)size);
actions if error or not etc.
}
#endif
#ifndef HAVE_UNLOCKED_IOCTL
unlock_kernel();
#endif
return ret;
}
#ifdef HAVE_UNLOCKED_IOCTL
long ndas_ctrldev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
#else
int ndas_ctrldev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
#endif
{
#ifdef HAVE_UNLOCKED_IOCTL
! add some sort of lock here !
#endif
lots of operations and functions.
#ifdef HAVE_UNLOCKED_IOCTL
! add unlock statement here !
#endif
return result;
}
static struct file_operations ndasctrl_fops = {
.write = ndas_ctrldev_write,
.read = ndas_ctrldev_read,
.open = ndas_ctrldev_open,
.release = ndas_ctrldev_release,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = ndas_ctrldev_ioctl,
#else
.ioctl = ndas_ctrldev_ioctl,
#endif
};
So, I would ask the following advice.
Does this look like the right
proceedure?
Do I understand correct to move the
lock into the io function?
Based on the includes in crtrldev.c, can you
recommend any lock off the top of
your head? (I tried to research some
other drivers dealing with filp and
lock_kernel, but I am too much a
noob to find the answer right away.)
The Big Kernel Lock (BKL) is more than deprecated - as of 2.6.39, it does not exist anymore.
The way the lock_kernel() conversion was done was to replace it by per-driver mutexes. If the driver is simple enough, you can simply create a mutex for the driver, and replace all uses of lock_kernel() and unlock_kernel() by the mutex lock/unlock calls. Note, however, that some functions used to be called with the BKL (the lock lock_kernel() used to lock) held; you will have to add lock/unlock calls to these functions too.
This will not work if the driver could acquire the BKL recursively; if that is the case, you would have to track it yourself to avoid deadlocks (this was done in the conversion of reiserfs, which depended somewhat heavily both in the recursive BKL behavior and in the fact that it was dropped when sleeping).
The next step after the conversion to a per-driver mutex would be to change it to use a per-device mutex instead of a per-driver mutex.
Here is the solution.
#if HAVE_UNLOCKED_IOCTL
#include <linux/mutex.h>
#else
#include <linux/smp_lock.h>
#endif
.
.
.
#if HAVE_UNLOCKED_IOCTL
mutex_lock(&fs_mutex);
#else
lock_kernel();
#endif
This only shows replacing the lock call. The other parts worked out as I guessed in the question part above concerning unlocked_ioctl. Thanks for checking and for helping.
I have one application which reads user default locale in Windows Vista and above. When i tried calling the API for getting User default Locale API is crashing. Below is the code, It will be helpfull if any points the reason
#include <iostream>
#include <WinNls.h>
#include <Windows.h>
int main()
{
LPWSTR lpLocaleName=NULL;
cout << "Calling GetUserDefaultLocaleName";
int ret = GetUserDefaultLocaleName(lpLocaleName, LOCALE_NAME_MAX_LENGTH);
cout << lpLocaleName<<endl;
}
You need to have lpLocaleName initialized to a buffer prior to calling the API. As a general consensus, if an API has a LPWSTR data type parameter, call malloc or new on it first, to the desired length, in this case, LOCALE_NAME_MAX_LENGTH. Setting it to NULL and passing it to the API function is a guaranteed way to crash!
Hope this helps,
Best regards,
Tom.
In addition to the previous answers, you should also be aware that you can't print a wide string with cout; instead, you should use wcout.
So:
#include <iostream>
#include <WinNls.h>
#include <Windows.h>
#define ARRSIZE(arr) (sizeof(arr)/sizeof(*(arr)))
using namespace std;
int main()
{
WCHAR_T localeName[LOCALE_NAME_MAX_LENGTH]={0};
cout<<"Calling GetUserDefaultLocaleName";
int ret = GetUserDefaultLocaleName(localeName,ARRSIZE(localeName));
if(ret==0)
cout<<"Cannot retrieve the default locale name."<<endl;
else
wcout<<localeName<<endl;
return 0;
}
I believe you need to initialise lpLocaleName to an empty string of 256 chars (for example) then pass the length (256) where you have LOCALE_NAME_MAX_LENGTH