Pre-R16B driver_async_port_key alternative - erlang

According to erl_driver documentation for driver_async_port_key function,
Before OTP-R16, the actual port id could be used as a key with proper casting, but after the rewrite of the port subsystem, this is no longer the case. With this function, you can achieve the same distribution based on port id's as before OTP-R16.
What is this proper casting?

The ErlDrvPort type is a typedef of a pointer to a struct. To obtain an unsigned int async key type in older driver applications, you need to convert this pointer type to unsigned int. One way to achieve this is to cast it through the C99 uintptr_t type, which is guaranteed to be large enough to hold a pointer value:
#include <stdint.h>
#include "erl_driver.h"
unsigned int my_port_key(ErlDrvPort port)
{
return (unsigned int) (uintptr_t) port;
}
You can write a portable function to return an async key using driver API versioning information available in erl_driver.h. The driver_async_port_key function was introduced in driver API version 2.2, so we can call driver_async_port_key when using version 2.2 or newer, or fall back to the casting approach for older versions:
#include <stdint.h>
#include "erl_driver.h"
unsigned int my_port_key(ErlDrvPort port)
{
#if ERL_DRV_EXTENDED_MAJOR_VERSION > 2 || \
(ERL_DRV_EXTENDED_MAJOR_VERSION == 2 && ERL_DRV_EXTENDED_MINOR_VERSION >= 2)
return driver_async_port_key(port);
#else
return (unsigned int) (uintptr_t) port;
#endif
}

Related

Usage of FunctionPass over ModulePass when creating LLVM passes

I've seen quite a numerous amount of examples that go over creating functions passes (e.g. Brandon Holt and Adrian Sampson), but I am curious as to the difficulty in creating a module pass to do these very similar problems. I've tried to implement a module pass to display the global variable names using this example and llvm source code to understand how you have to iterate through members.
I am using a source compiled version of LLVM, and using the example from the above links to add the pass, and then running:
$ clang -Xclang -load -Xclang build/Skeleton/libSkeletonPass.so something.c
Which then returns this gibberish. However, if I implement a functionPass and just use Auto to determine the type to be initialized it's very straight forward and works. Am I just going about printing the global variables the wrong way?
This is a pastebin of the error output from the terminal. link
Skeleton.cpp
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/LLVMContext.h"
using namespace llvm;
namespace {
// Helper method for converting the name of a LLVM type to a string
static std::string LLVMTypeAsString(const Type *T) {
std::string TypeName;
raw_string_ostream N(TypeName);
T->print(N);
return N.str();
}
struct SkeletonPass : public ModulePass {
static char ID;
SkeletonPass() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
for (Module::const_global_iterator GI = M.global_begin(),
GE = M.global_end(); GI != GE; ++GI) {
errs() << "Found global named: " << GI->getName()
<< "\tType: " << LLVMTypeAsString(GI->getType()) << "!\n";
}
return false;
}
};
}
char SkeletonPass::ID = 0;
// Automatically enable the pass.
// http://adriansampson.net/blog/clangpass.html
static void registerSkeletonPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) {
PM.add(new SkeletonPass());
}
static RegisterStandardPasses
RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
registerSkeletonPass);
something.c
int value0 = 5;
int main(int argc, char const *argv[])
{
int value = 4;
value += 1;
return 0;
}
I was able to figure this out after some extensive github searching. Here is the answer from which I was following a tutorial to help others who may be curious how to implement a Module Pass.

What is the type of pthread_mutex_t?

From: https://www.sourceware.org/pthreads-win32/manual/pthread_mutex_init.html
Variables of type pthread_mutex_t can also be initialized statically,
So, what is the type of pthread_mutex_t?
That is the type. The implementation underneath is often a struct and you can look in the header files if you really care about the specific implementation of the library you're using, but those details don't matter for using it, you just care about the pthread_mutex_t type.
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
From pthreadtypes.h, in my Linux distribution its definition is pretty clear as a typedef for a union, as defined below:
/* Data structures for mutex handling. The structure of the attribute
type is not exposed on purpose. */
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
You'll want to use it as their defined type, pthread_mutex_t of course -- since this type will vary by OS / distribution / etc.
pthread_mutex_t is a type, so it doesn't have a type itself. If you are curious about what this type is an alias for, on my machine I have:
struct _opaque_pthread_mutex_t {
long __sig;
char __opaque[__PTHREAD_MUTEX_SIZE__];
};
and then
typedef struct _opaque_pthread_mutex_t __darwin_pthread_mutex_t;
and finally:
typedef __darwin_pthread_mutex_t pthread_mutex_t;

About the parameter of function pthread_create?

We know that we call pthread like this:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void* arg);
Hi guys, i want to know why the return type of third parameter is void*? why not void?
Because there is no way for a start function to know what kind of data a developer wants to return from the function they use a void* that can point to any type. It is up to the developer of the start function to then cast the void* to appropriate type he actually returned before using whatever the void* points to. So now the start function can return a pointer that may in actually point to anything. If the start function is declared to return void, it means this function returns nothing, then what if the developer wants the start function to return a int, a struct? For example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
struct test {
char str[32];
int x;
};
void *func(void*) {
struct test *eg = (struct test *)malloc(sizeof(struct test));
strcpy(eg->str,"hello world");
eg->x = 42;
pthread_exit(eg);
}
int main (void) {
pthread_t id;
struct test *resp;
pthread_create(&id, NULL, func, NULL);
pthread_join(id,(void**)&resp);
printf("%s %d\n",resp->str,resp->x);
free(resp);
return 0;
}
More details on this post: What does void* mean and how to use it?

How to create and using vapi files?

I want to make a custom vapi file, I have the basic stuff but I obviously miss something and I can't find anywhere how to do this properly. My main goal is to create a torent app, using libtorrent, and create the GUI (the frontend?) with vala and gtk.
I have a c_func_head.h:
#ifndef WHATEVER_H_INCLUDED
#define WHATEVER_H_INCLUDED
int add(int a, int b);
#endif
c_functions.c:
#include <stdio.h>
#include <stdlib.h>
#include "c_func_head.h"
int add(int a, int b){
printf("Adding numbers in c...\n");
return a+b;
}
vala_p.vapi:
[CCode (cheader_filename = "c_func_head.h")]
namespace MyFunc {
[CCode (cname = "add")]
public int add (int a, int b);
}
and finally vala_program.vala:
//extern int add(int a, int b);
using MyFunc;
void main(){
stdout.printf("Calling a c function...\n");
//stdout.printf("The sum is: %d\n", add2number(2, 2));
int sum = add(2, 2);
stdout.printf("The sum is: %d\n", sum);
}
As you can see I used an extern too, it worked with it but I want to use vapi files.
I compiled with (everything is in the same folder):
valac vala_program.vala --vapidir=vala_p.vapi -o mustrun
and the error is:
The namespace name `MyFunc' could not be found using MyFunc;
One more thing. Is it possible to make bindings for libtorrent? It uses c++ and I gues I have to use c++ too.
You can't make Vala bindings of C++ code. Only C. There a a guide to writing legacy bindings and a binding for Transmission, which is C-based.
As for the specific error you have, you want to call valac vala_program.vala vala_p.vapi if the library (i.e., header files) are the the same directory or valac vala_program.vala --pkg vala_p --vapidir=/path/to/directory/containing/vapi.

Regarding use of __device__ for variables

I am using a global variable say d_myVar, which will be allocated device memory using cudaMalloc in main function. I am not clear, should I use __ device __ in front of it while doing global declaration? I ask this, since if it were local variable in host and was passed to a kernel, we would not write __ device __ in front of it. Let me know if I am wrong.
Globally-scoped __device__ variables are not allocated with cudaMalloc. Simply annotate a variable in the global scope with __device__:
#include <stdio.h>
__device__ int d_myVar;
__global__ void foo()
{
printf("d_myVar is %d\n", d_myVar);
}
int main()
{
int h_myVar = 13;
cudaMemcpyToSymbol(d_myVar, &h_myVar, sizeof(int), 0, cudaMemcpyHostToDevice);
foo<<<1,1>>>();
cudaThreadSynchronize();
return 0;
}
The result:
$ nvcc -arch=sm_20 test.cu -run
d_myVar is 13

Resources