Exporting TASKLET in kernel module? - module

I got two kernel modules which both exports some symbols using EXPORT_SYMBOL().
One of them exports basic function (sv1<-sv2) and it works but I got problem with the other one (sv1->sv2).
What I want is to export TASKLET. I read somewhere that is possibile and there is no proscription of doing this. Module nr 1 (called sv1) consists of BH Function and declaration of tasklet:
struct tasklet_struct sv_takslet;
EXPORT_SYMBOL(sv_takslet);
void sv_tasklet_function( unsigned long data )
{
printk( "%s\n", (char *)data );
return;
}
static int __init sv_publisher_init(void)
{
...
tasklet_init(&sv_takslet, &sv_tasklet_function,&sv_tasklet_data);
...
}
In second module there is global reference and task_schedule() function used at initialization of the module nr 2 (called sv2):
extern struct tasklet_struct sv_takslet;
...
tasklet_schedule(&sv_takslet);
The problem is when I got:
tasklet_schedule(&sv_takslet);
in my code I do not see my two modules on list (modprobe -l), but when I comment this line on sv2- they magically appear.
What could be a cause of that behavior? Is this initialization is correct?
EDIT
The cause of this problem is that module sv2 is loading before sv1 and has no knowledge about the tasklet (line: extern struct tasklet_struct sv_takslet). When I change destination that sv2 exports TASKLET to sv1 the problem is gone.
But now I am facing with that both modules have to export symbols to each other. I have no idea how to solve this problem...
Both *.c files are in the same directory and my Makefile has following line:
obj-m += sv_publisher.o zsv_core.o
Does anybody have some tips how to go about it?

Related

How can Poplar codelets include code from other header files?

Is it possible for codelets to reference code in other files, like header files?
If I have a codelet file
//FileA.cpp
#include "FileB.h"
class SomeCustomVertex : public Vertex {
public:
bool compute() {
int a = SomeConstantDefinedInFileB;
}
...
}
and some other "codelet" file
//FileB.h
const int SomeConstantDefineInFileB = 42;
and in the host graph program:
graph.addCodelets({"codelets/FileA.cpp", "codelets/FileB.h"});
I get a compile error from popc:
fatal error: 'FileB.h' file not found
#include "FileB.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
terminate called after throwing an instance of 'poplar::graph_program_compilation_error'
what(): Codelet compilation failed (see compiler output for details)
I figured this out.
Graph::addCodelets has a parameter StringRef compileFlags = "", which you can use to inject compiler options.
popc --help shows an option
-I arg Add directory to include search path
So when I use graph.addCodelets({"codelets/FileA.cpp"}, "-I codelets"); in the host program, and have my codelets in 'codelets' subdirectory, this works. No need to explicitly list the ".h" files in the arguments.
Incidentally, also a good way to ensure compiler optimisation (-O3) for the custom codelets.

How to create a Dynamic Library in D?

I want to create a Dynamic library (cross-platform) in D, so I did some Googling. After some time I found this page. I am absolutely stunned by how much complexities there are in writing, compiling and even linking to a DLL. Isn't there a uniform way of creating a shared library like you would in C? (just leave out the main function and pass some flags to the linker)
Well, I decided to spend some time today messing with this and I kinda sorta have something that works, at least if the main program is also written in D (on Linux, I think it will work from C too on Windows. The reason is I didn't link to phobos in the .so in the D one, so it relies upon the exe for those symbols. I think, tbh I don't know exactly what is going on here, maybe it would work better if I used the shared phobos lib too)
Anyway, first, let's throw some code down.
This is testdll.d and it builds our dll
module testdll;
import std.stdio;
extern(C)
export void lol() {
import core.stdc.stdio;
printf("hello from C\n");
writeln("hello!");
}
version(Windows)
extern(Windows) bool DllMain(void* hInstance, uint ulReason, void*) {
import std.c.windows.windows;
import core.sys.windows.dll;
switch (ulReason)
{
default: assert(0);
case DLL_PROCESS_ATTACH:
dll_process_attach( hInstance, true );
break;
case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
}
return true;
}
You'll notice most that code is the WinMain which just calls druntime functions. I think that main should be available at least as a mixin, or maybe even fully automatic, since it is pure boilerplate.
And the client code:
import core.runtime;
alias extern(C) void function() functype;
version(Posix) {
extern(C) void* dlsym(void*, const char*);
extern(C) void* dlopen(const char*, int);
extern(C) char* dlerror();
pragma(lib, "dl");
} else version(Windows) {
extern(Windows) void* LoadLibraryA(const char* filename);
extern(Windows) void* GetProcAddress(void*, const char*);
}
void main() {
version(Posix) {
auto thing = dlopen("./testdll.so", 2);
if(thing is null) {
import std.conv;
import std.stdio;
writeln(to!string(dlerror()));
return;
}
auto proc = cast(functype) dlsym(thing, "lol");
} else version(Windows) {
auto thing = LoadLibraryA("testdll.dll");
assert(thing !is null);
auto proc = cast(functype) GetProcAddress(thing, "lol");
}
assert(proc !is null);
//import std.stdio; writeln("calling proc");
proc();
}
This has different code for Windows and Linux, though it is pretty similar. The druntime stuff is supposed to start taking care of this soon as we mentioned in the comments.
The compile commands aren't too bad but a little weird. Linux first:
dmd -fPIC -shared testdll.d -defaultlib= # builds the dll
PIC and shared tell it to build the .so. I did the blank defaultlib because without it, loading the dll at runtime failed with "symbol already defined" errors.
Building the client is straightforward:
dmd testdllc.d
Note that there's the pragma(lib) in the file that links with the -ldl option automatically. Run it and get some hello! BTW be sure both are in the same directory since this loads ./ in the loader.
Now, let's build on Windows.
dmd -oftestdll.dll -shared testdll.d testdll.def
Tell it to output our dll, use -shared so it knows, and then the other thing is the def file, like described here http://dlang.org/dll.html/dllmain
These are the contents of that file:
LIBRARY testdll
EXETYPE NT
CODE SHARED EXECUTE
DATA WRITE
EXPORTS
lol
If you don't use the .def file, the dll will build successfully, but the procedure won't be found because it isn't exported. (I think the export keyword in D should be able to do this automatically, bypassing hte .def file, and I believe there's a discussion on doing this, but right now it is required as far as I know.)
And the client is similarly easy:
dmd testdllc.d
Run it and get some hellos, if all goes well.
Now, why did I do the functype alias in the client? Easier than doing the other casting and such, and it makes it nicely extern(C).
Why is the lol function extern(C) in the first place? Just so it has an easier name to use in GetProcAddress/dlsym. Could have also pragma(mangle) or did .mangleof with an import thing. All kinds of options there, fairly straightforward, I just wanted to keep it simple to make the test easier to focus on. "lol" is a simpler name than "_D7testdll3lolFZv" or whatever the mangled name would be.... (OMG I mangled it correctly by hand! Sometimes I think I write too much D lol) and yeah that works too it is just harder to do by eyeball. Note: on Windows, the .def file might have to leave off the leading underscore if you do it that way.
anyway, yeah, this made a working dll/so for me and a program to load and use it successfully. Not as pretty as it could/should be, but it works. For me at least.

OpenNI 1.5::Could not run code from documentation

I am trying to run a sample code from the OpenNI 1.5 documentation.I have imported the library required XnCppWrapper.h so that I can use C++.The code has only one error on a particular variable "bshouldrun".I know that it should be declared as something but since I am new at this and the documentation does not contain anything above the main, I dont know what to declare it as..Please help!!
And thanks in advance.
#include <XnOpenNI.h>
#include <XnCppWrapper.h>
#include <stdio.h>
int main()
{
XnStatus nRetVal = XN_STATUS_OK;
xn::Context context;
// Initialize context object
nRetVal = context.Init();
// TODO: check error code
// Create a DepthGenerator node
xn::DepthGenerator depth;
nRetVal = depth.Create(context);
// TODO: check error code
// Make it start generating data
nRetVal = context.StartGeneratingAll();
// TODO: check error code
// Main loop
while (bShouldRun) //<-----------------------------**ERROR;bShouldRun Undefined**
{
// Wait for new data to be available
nRetVal = context.WaitOneUpdateAll(depth);
if (nRetVal != XN_STATUS_OK)
{
printf("Failed updating data: %s\n", xnGetStatusString(nRetVal));
continue;
}
// Take current depth map
const XnDepthPixel* pDepthMap = depth.GetDepthMap();
// TODO: process depth map
}
// Clean-up
context.Shutdown();
}
Here's what I did to run a sample from Visual Studio 2010 Express on Windows (8):
Opened the NiSimpleViewer.vcxproj VS2010 project from C:\Program Files (x86)\OpenNI\Samples\NiSimpleViewer
Edited OpenNI.rc to comment out #include "afxres.h" on line 10(might be missing this because I'm using Express version, not sure. Your machine might compile this fine/not complain about the missing header file)
Enabled Tools > Options > Debugging > Symbols > Microsoft Symbol Servers (to get past missing pdb files issue)
Optionally edit the SAMPLE_XML_PATH to "SamplesConfig.xml" rather than the default "../../../Data/SamplesConfig.xml", otherwise you need to run the sample executable from ..\Bin\Debug\NiSimpleViewer.exe by navigating to there rather than using the Ctrl+F5. A;so copy the SamplesConfig.xml file into your sample folder as you can see bellow
Here are a few images to illustrate some of the above steps:
You can also compile the NiHandTracker sample, which sounds closer to what you need.
So this explains the setup for OpenNI 1.5 which is what your question is about.
I've noticed your OpenNI 2 lib issue in the comments. It should be a matter of linking against SimpleHandTracker.lib which you can do via Project Properties (right-click project->select Properties) > Linker > Input > Additional Dependencies > Edit.
I don't have OpenNI2 setup on this machine, but assuming SimpleHandTracker.lib would be in OpenNI_INSTALL_FOLDER\Lib. Try a file search in case I might be wrong.

how to iterate over PCB's to show information in a Linux Kernel Module?

I want to write a little Linux Kernel Module that can show me the PID of all running processes.
I have the following code:
/*
* procInfo.c My Kernel Module for process info
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
/*
* The init function, called when the module is loaded.
* Returns zero if successfully loaded, nonzero otherwise.
*/
static int mod_init(void)
{
printk(KERN_ALERT "ProcInfo sucessfully loaded.\n");
return 0;
}
/*
* The exit function, called when the module is removed.
*/
static void mod_exit(void)
{
printk(KERN_ALERT "ProcInfo sucessfully unloaded.\n");
}
void getProcInfo()
{
printk(KERN_INFO "The process is \"%s\" (pid %i)\n",
current->comm, current->pid);
}
module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rodrigo");
As you can see, i know i have to use the *struct task_struct* structure to get the PID and the Process name, but i am using current, and i know the existance of some double linked circular list that contains all PCB's, so the main question is:
what do i need to add to iterate over this linked lisk with p-next_task and p-prev_task so getProcInfo works?
Thanks!
The following macros from include/linux/sched.h may be useful:
#define next_task(p) \
list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
You probably need to hold the tasklist_lock before calling these macros; several examples of how to lock, iterate, and unlock, are in mm/oom_kill.c.
Actually, for newer kernels (2.6.18 and newer) the proper way to list tasks is by holding an rcu lock, because task list is now an RCU list. Also tasklist_lock is no more exported symbol - it means that when you are compiling a loadable kernel module, this symbol will not be visible for you.
example code to use
struct task_struct *task;
rcu_read_lock();
for_each_process(task) {
task_lock(task);
/* do something with your task :) */
task_unlock(task);
}
rcu_read_unlock();
Also documentation about RCU in linux kernel source directory can be helpful and you will find it in Documentation/RCU

Symbian: kern-exec 3 panic on RLibrary::Load

I have troubles with dynamic loading of libraries - my code panics with Kern-Exec 3. The code is as follows:
TFileName dllName = _L("mydll.dll");
TFileName dllPath = _L("c:\\sys\\bin\\");
RLibrary dll;
TInt res = dll.Load(dllName, dllPath); // Kern-Exec 3!
TLibraryFunction f = dll.Lookup(1);
if (f)
f();
I receive panic on TInt res = dll.Load(dllName, dllPath); What can I do to get rid of this panic? mydll.dll is really my dll, which has only 1 exported function (for test purposes). Maybe something wrong with the DLL? Here's what it is:
def file:
EXPORTS
_ZN4Init4InitEv # 1 NONAME
pkg file:
#{"mydll DLL"},(0xED3F400D),1,0,0
;Localised Vendor name
%{"Vendor-EN"}
;Unique Vendor name
:"Vendor"
"$(EPOCROOT)Epoc32\release\$(PLATFORM)\$(TARGET)\mydll.dll"-"!:\sys\bin\mydll.dll"
mmp file:
TARGET mydll.dll
TARGETTYPE dll
UID 0x1000008d 0xED3F400D
USERINCLUDE ..\inc
SYSTEMINCLUDE \epoc32\include
SOURCEPATH ..\src
SOURCE mydllDllMain.cpp
LIBRARY euser.lib
#ifdef ENABLE_ABIV2_MODE
DEBUGGABLE_UDEBONLY
#endif
EPOCALLOWDLLDATA
CAPABILITY CommDD LocalServices Location MultimediaDD NetworkControl NetworkServices PowerMgmt ProtServ ReadDeviceData ReadUserData SurroundingsDD SwEvent TrustedUI UserEnvironment WriteDeviceData WriteUserData
source code:
// Exported Functions
namespace Init
{
EXPORT_C TInt Init()
{
// no implementation required
return 0;
}
}
header file:
#ifndef __MYDLL_H__
#define __MYDLL_H__
// Include Files
namespace Init
{
IMPORT_C TInt Init();
}
#endif // __MYDLL_H__
I have no ideas about this... Any help is greatly appreciated.
P.S. I'm trying to do RLibrary::Load because I have troubles with static linkage. When I do static linkage, my main program doesn't start at all. I decided to check what happens and discovered this issue with RLibrary::Load.
A KERN-EXEC 3 panic is caused by an unhandled exception (CPU fault) generated by trying to invalidly access a region of memory. This invalid memory access can be for both code (for example, bad PC by stack corruption) or data (for example, accessing freed memory). As such these are typically observed when dereferencing a NULL pointer (it is equivalent to a segfault).
Certainly the call to RLibrary::Load should never raise a KERN-EXEC 3 due to programmatic error, it is likely to be an environmental issue. As such I have to speculate on what is happening.
I believe the issue that is observed is due to stack overflow. Your MMP file does not specify the stack or heap size the initial thread should use. As such the default of 4Kb (if I remember correctly) will be used. Equally you are using TFileName - use of these on the stack is generally not recommended to avoid... stack overflow.
You would be better off using the _LIT() macro instead - this will allow you to provide the RLibrary::Load function with a descriptor directly referencing the constant strings as located in the constant data section of the binary.
As a side note, you should check the error value to determine the success of the function call.
_LIT(KMyDllName, "mydll.dll");
_LIT(KMyDllPath, "c:\\sys\\bin\\");
RLibrary dll;
TInt res = dll.Load(KMyDllName, MyDllPath); // Hopefully no Kern-Exec 3!
if(err == KErrNone)
{
TLibraryFunction f = dll.Lookup(1);
if (f)
f();
}
// else handle error
The case that you can't use static linkage should be a strong warning to you. It shows that there is something wrong with your DLL and using dynamic linking won't change anything.
Usually in these cases the problem is in mismatched capabilities. DLL must have at least the same set of capabilities that your main program has. And all those capabilities should be covered by your developer cert.