I am attempting to create a system call that will increment a number that was added to the cpu struct. However I believe that a sys call has to be void so how can I pass in a value when calling it for example.
incrementNum(3);
Xv6 has its own functions for passing arguments from user space to kernel space (system call). You can use argint() to retrieve integer arguments in your system call and argstr() to retrieve string arguments.
Passing arguments can be done the traditional way but for retrieving the arguments, you must use these methods. In your case:
In syscall.c :
extern int incrementNum(int);
static int (*syscalls[])(void) = {
...
[SYS_incrementNum] sys_incrementNum,
};
In syscall.h
#define SYS_incrementNum 22
In user.h
int incrementNum(int);
In Usys.S
SYSCALL(incrementNum);
In sysproc.c (where you want to retrieve the argument)
int
sys_incrementNum(int num)
{
argint(0,&num); //retrieving first argument
cprintf("%d - Inside system call!",num);
}
Calling the system call can now be done via:
incrementNum(3);
In sysproc.c ,declare the function as having void argument.hen retrieve the arguments inside.For rest,follow #Sravani's answer.
int
sys_incrementNum(void)
{
int num;
argint(0,&num); //retrieving first argument
cprintf("%d - Inside system call!",num);
return num + 1;
}
Related
I am reading the source code of a UART peripheral and there is a function as below:
eResult = adi_stdio_ControlDevice (hSTDIOUART,
ADI_STDIO_COMMAND_SET_UART_BAUD_RATE, (void *)57600);
This function is used to connect UART and number 57600 is the baudrate. What I do not understand is the meaning of (void*)57600.
I think this maybe a pointer to const and the return value of (void*)57600 is 57600. When we use (void*)57600, does it mean we are creating a pointer that points to the 57600 value?
And why we must use (void*)57600?
Not quite. The "return value" (quoted because it's not actually being returned from a function, instead it's the result of a cast) of (void *)57600 is simply the value 57600 being treated as (or, in other words, cast to) a void pointer.
And, while you are actually converting 57600 to a void pointer, it's almost certainly not being used as a pointer. More likely is that the prototype for adi_stdio_ControlDevice has a generic argument (one that can be used for many things).
Device control functions are particularly apt to do that since they are meant to be generic across a large variety of devices, so you may have to give a wide variety of types to the calls.
You'll probably find that, for the command to set the baud rate, it simply gets cast back to an integral value at the other end before being used, something like:
static int localSpeed;
static char *localString;
static double localPi;
static struct rational { int numerator; int denominator } localStruct;
bool adi_stdio_ControlDevice (HANDLE hndl, COMMAND cmd, void *generic) {
switch (cmd) {
case ADI_STDIO_COMMAND_SET_UART_BAUD_RATE: {
localSpeed = (int)generic;
break;
}
case ADI_COMMAND_WITH_STRING_ARG: {
if (localString) free(localString);
localString = strdup((char*)generic);
break;
}
case ADI_COMMAND_WITH_DOUBLE_PTR_ARG: {
localPi = *((double*)generic));
break;
}
case ADI_COMMAND_WITH_STRUCT_PTR: {
memcpy(localStruct, generic, sizeof(localStruct));
break;
}
}
}
Other commands (such as the fake ones I've added) would be able to use the generic argument in a variety of ways, as integers or other pointer types for example.
This is actually supported by the documentation (VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors) for that call, which states:
ADI_STDIO_RESULT adi_stdio_ControlDevice (
ADI_STDIO_DEVICE_HANDLE hStdioDevice,
uint32_t nCommandID,
void *const pValue
);
: : :
pValue: Argument required for executing the command. Depending upon the command, different types of arguments are required.
Documentation: http://doc.qt.io/qt-5/qflags.html#operator-Int
The question. I want to know what flags are set withouth testing one by one so I want the int number. Can anyone provide an example of how to use that operator in one of the many qt methods that rerturn a QFlags?
By referring to QFlags.h source code (https://android.googlesource.com/platform/prebuilts/android-emulator-build/qt/+/master/common/include/QtCore/qflags.h)
This is the definition in QFlags for "Int" operator.
Q_DECL_CONSTEXPR inline operator Int() const Q_DECL_NOTHROW { return i; }
And the "i" in return statement is declared as
Int i;
And the "Int" is declared as
typedef int Int
Notice the below two constructors of QFlags. The first constructor takes Enum as parameter and the second constructor takes QFlag as parameter.
Q_DECL_CONSTEXPR inline QFlags(Enum f) Q_DECL_NOTHROW : i(Int(f)) {}
Q_DECL_CONSTEXPR inline QFlags(QFlag f) Q_DECL_NOTHROW : i(f) {}
After noticing the above constructors, if Enum is passed to the constructor, the Enum can be a signed one or unsigned one. QFlags internally type casts it to int using Int.
Consider below example now.
//Qt::CursorShape is an Enum
Qt::CursorShape shape = Qt::ArrowCursor;
//Create QFlags object by passing "ENUM" as parameter
QFlags<Qt::CursorShape> qF(shape);
//Create QFlags object by just passing FLAG as a parameter
QFlags<Qt::CursorShape> q(Qt::ArrowCursor);
Now the situation where "Int" operator is called: In the below piece of code the first statement invokes Int operator and not in the second statement.
//Now try getting the values.
int test = qF; //In this case the "Int" operator is called.
int test1 = q;
Say I want to invoke a CUDA kernel, like this:
struct foo { int a; int b; float c; double d; }
foo arg;
// fill in elements of `arg` here
my_kernel<<<grid_size, block_size, 0, stream>>>(arg);
Assume that stream was previously created using a call to cudaStreamCreate(), so the above will execute asynchronously. I'm concerned about the required lifetime of arg.
Are the arguments to the kernel copied synchronously when I invoke it (so it would be safe for arg to go out of scope immediately), or are they copied asynchronously (so I need to ensure that it stays alive until the kernel runs)?
Arguments are copied synchronously at launch. The API exposes a call stack onto which execution parameters and function arguments are pushed in order, then a call finalises those arguments into a CUDA kernel launch on the drivers internal streams/command queues.
This process isn't documented, but as of CUDA 7.5, a runtime API kernel launch like this:
dot_product<<<1,n>>>(n, d_a, d_b);
becomes this:
(cudaConfigureCall(1, n)) ? (void)0 : (dot_product)(n, d_a, d_b);
where the host stub function dot_product is expanded into this:
void __device_stub__Z11dot_productiPfS_(int __par0, float *__par1, float *__par2)
{
if (cudaSetupArgument((void *)(char *)&__par0, sizeof(__par0), (size_t)0UL) != cudaSuccess) return;
if (cudaSetupArgument((void *)(char *)&__par1, sizeof(__par1), (size_t)8UL) != cudaSuccess) return;
if (cudaSetupArgument((void *)(char *)&__par2, sizeof(__par2), (size_t)16UL) != cudaSuccess) return;
{
volatile static char *__f __attribute__((unused)); __f = ((char *)((void ( *)(int, float *, float *))dot_product));
(void)cudaLaunch(((char *)((void ( *)(int, float *, float *))dot_product)));
};
}
void dot_product( int __cuda_0,float *__cuda_1,float *__cuda_2)
{
__device_stub__Z11dot_productiPfS_( __cuda_0,__cuda_1,__cuda_2);
}
cudaSetupArgument is the API call which is pushing arguments onto the call stack. Interestingly, this is actually deprecated in the API documentation for CUDA 7.5, even though the compiler is using it. I would, therefore, expect this to change in the future, but the idea will be the same.
The parameters of the kernel call are copied prior to execution, so the scope schould be of no concern. But please note that the size of all kernel parameters cannot exceed a maximum size in bytes. If you want larger structs or blobs of data you need to allocate the used memory on the device using cudaMalloc, then copy the content of the host struct to the device struct using cudaMemcpy and call the kernel with a pointer to the new device struct.
Your code would look something like this:
struct foo { int a; int b; float c; double d; }
foo arg;
foo *arg_d;
// fill in elements of `arg` here
cudaMalloc(&arg_d, sizeof(foo));
// check the allocation here
cudaMemcpy(arg_d, &arg, sizeof(foo), cudaMemcpyHostToDevice);
my_kernel<<<grid_size, block_size, 0, stream>>>(arg_d);
like: vector<void *(*func)(void *)>...
You can declare a vector of pointers to functions taking a single void * argument and returning void * like this:
#include <vector>
std::vector<void *(*)(void *)> v;
If you want to store pointers to functions with varying prototypes, it becomes more difficult/dangerous. Then you must cast the functions to the right type when adding them to the vector and cast them back to the original prototype when calling. Just an example how ugly this gets:
#include <vector>
int mult(int a) { return 2*a; }
int main()
{
int b;
std::vector<void *(*)(void *)> v;
v.push_back((void *(*)(void *))mult);
b = ((int (*)(int)) v[0])(2); // The value of b is 4.
return 0;
}
You can use typedef's to partially hide the function casting syntax, but there is still the danger of calling a function as the wrong type, leading to crashes or other undefined behaviour. So don't do this.
// shorter
std::vector<int (*)(int)> v;
v.push_back(mult);
b = v[0](2); // The value of b is 4.
Storing a function in vector might be a difficult task as illustrated above. In that case if u want to dynamically use a function u can also store a function in pointer which is much easier. Main advantage of this is u can store any type of function either it is a normal function or a paramatrized one(having some input as parametrs). Complete process is described in the link given below with examples...just have a look...!!!
how can we store Function in pointer
I'm using Qt Creator 4.5 with GCC 4.3 and I'm having the following problem that I am not sure is Qt or C++ related: I call a function with a char * as an input parameter. Inside that function I make a dynamic allocation and I assign the address to the char *. The problem is when the function returns it does not point to this address anymore.
bool FPSengine::putData (char CommandByte , int Index)
{
char *msgByte;
structSize=putDatagrams(CommandByte, Index, msgByte);
}
int FPSengine::putDatagrams (char CommandByte, int Index, char *msgByte)
{
int theSize;
switch ( CommandByte ) {
case (CHANGE_CONFIGURATION): {
theSize=sizeof(MsnConfigType);
msgByte=new char[theSize];
union MConfigUnion {
char cByte[sizeof(MsnConfigType)];
MsnConfigType m;
};
MConfigUnion * msnConfig=(MConfigUnion*)msgByte;
...Do some assignments. I verify and everything is OK.
}
}
return theSize;
}
When I return the pointer it contains a completely different address than the one assigned in putDatagrams(). Why?
...
Ok thx I understand my mistake(rookie mistake :( ). When sending a pointer as an input parameter to the function you send the address of your data but not the address of your pointer so you cant make the pointer point somewhere else...it is actually a local copy like Index. The only case the data would of been returned succesfully with the use of a char * is by allocating the memory before the function call:
bool FPSengine::putData (char CommandByte , int Index)
{
char *msgByte;
msgByte=new char[sizeof(MsnConfigType)];
structSize=putDatagrams(CommandByte, Index, msgByte);
}
int FPSengine::putDatagrams (char CommandByte, int Index, char *msgByte)
{
int theSize;
switch ( CommandByte ) {
case (CHANGE_CONFIGURATION): {
theSize=sizeof(MsnConfigType);
union MConfigUnion {
char cByte[sizeof(MsnConfigType)];
MsnConfigType m;
};
MConfigUnion * msnConfig=(MConfigUnion*)msgByte;
...Do some assignments. I verify and everything is OK.
}
}
return theSize;
}
There are two ways. The pass-by-value way (C style):
int FPSengine::putDatagrams (char CommandByte, int Index, char **msgByte)
Note the second * for msgByte. Then inside of putDatagrams(), do:
*msgByte = new char[theSize];
In fact, anywhere in that function where you currently have msgByte, use *msgByte. When calling putDatagrams(), do:
structSize=putDatagrams(CommandByte, Index, &msgByte);
And the second way, since you're in C++, you could use pass-by-reference. Just change the signature of putDatagrams() to:
int FPSengine::putDatagrams (char CommandByte, int Index, char * &msgByte)
And you should be good. In this case, you shouldn't need to modify the caller or anything inside of your putDatagrams() routine.
Well, yes. Everything in C++ is, by default, passed by value. Parameters in the call putDatagrams(a, b, c) are sent by value - you wouldn't expect assigning to index in the code to change the value of b at the call site. Your msgByte=new char[theSize]; is just assigning to the local variable msgByte, overwriting the value passed in.
If you want to change a passed parameter such that the call site variable changes, you'll need to either pass by reference, or (in this case) pass a "pointer to a pointer` (and deference away the first pointer, assigning to the actual pointer).