I think that I am missing something fundamental with regards to pointers. I have the following code:
alicat_data *data = (alicat_data*)ent.second->get_data();
if(ent.first == "AlicatA"){
ui->ac0_P->setValue(data->pressure);
ui->ac0_T->setValue(data->temperature);
ui->ac0_Q->setValue(data->flow_rate);
ui->ac0_Q0->setValue(data->mass_flow_rate);
ui->ac0_Qsp->setValue(data->setpoint);
}
which references a struct that is defined as follows:
struct alicat_data : Data {
float pressure; /** Pressure in mb */
float temperature; /** Temperature in degC */
float flow_rate; /** Volumetric low rate; units are defined by the model */
float mass_flow_rate; /** Mass flow rate; units are defined by the model */
float setpoint; /** Device setpoint (if it is a controller); units are defined by the model */
gas gas_; /** Enum as defined above representing the gas */
alicat_data(float p = 0, float T = 0, float Q = 0,
float Q0 = 0, float sp = 0, gas g = Air):pressure(p),
temperature(T), flow_rate(Q), mass_flow_rate(Q0),
setpoint(sp), gas_(g){
setTime();
}
virtual std::string serialize2ascii(){return std::to_string(pressure)
+ "\t" + std::to_string(temperature)
+ "\t" + std::to_string(flow_rate) + "\t" + std::to_string(mass_flow_rate)
+ "\t" + std::to_string(setpoint);}
};
When the topmost code is executed, the first reference, data->pressure returns correctly then it looks like everything at that address becomes garbage and data returned subsequent to this first reference (i.e. data->temperature, etc) is not correct.
I can fix this by doing the following
alicat_data data_ = *data;
but would prefer not to do this. What am I doing wrong that is creating the issue that I am seeing?
With get_data() you are getting pointer to block of memory of alicat_data and it is stored into the varable alicat_data *data, that is a pointer.
With alicat_data data_ = *data; you are getting the block of memory of the instance, so you can access its methods and properties with a dot '.'.
You can remove the variable alicat_data data_ = *data; and use the variable alicat_data *data as follow:
for (auto const &ent : alicat_map){
alicat_data *data = (alicat_data*)ent.second->get_data();
if(ent.first == "AlicatA"){
ui->ac0_P->setValue(data->pressure);
ui->ac0_T->setValue(data->temperature);
ui->ac0_Q->setValue(data->flow_rate);
ui->ac0_Q0->setValue(data->mass_flow_rate);
ui->ac0_Qsp->setValue(data->setpoint);
}
}
Update: Check this link to review the theory of pointers http://www.cplusplus.com/doc/tutorial/pointers/
Also I made a program with some of you to show you the tow ways, your and mine:
#include <iostream>
#include <map>
using namespace std;
struct alicat_data {
float pressure; /** Pressure in mb */
float temperature; /** Temperature in degC */
float flow_rate; /** Volumetric low rate; units are defined by the model */
float mass_flow_rate; /** Mass flow rate; units are defined by the model */
float setpoint; /** Device setpoint (if it is a controller); units are defined by the model */
alicat_data(float p = 0, float T = 0, float Q = 0,
float Q0 = 0, float sp = 0) {
pressure = p;
temperature = T;
flow_rate = Q;
mass_flow_rate = Q0;
setpoint = sp;
}
virtual std::string serialize2ascii() {
return "dummy";
}
};
int main()
{
map<string, alicat_data *> alicat_map;
map<string, alicat_data *>::iterator entM;
alicat_map["AlicatA"] = new alicat_data(1.1,2.2,3.3,4.4,5.5);
alicat_map["AlicatB"] = new alicat_data(12.1, 23.2, 34.3, 45.4, 56.5);
//Your Way
for (auto const &ent : alicat_map) {
alicat_data *data = (alicat_data*)ent.second; //Get the alicat_data* (pointer) element
if (ent.first == "AlicatA") {
alicat_data data_ = *data;
float pressure = data_.pressure;
float temp = data_.temperature;
float rate = data_.flow_rate;
float mflowrate = data_.mass_flow_rate;
float setpoint = data_.setpoint;
}
}
//My Way
for (entM = alicat_map.begin(); entM != alicat_map.end(); entM++)
{
alicat_data *data = entM->second; //Get the alicat_data* (pointer) element
if (entM->first == "AlicatA") {
float pressure = data->pressure;
float temp = data->temperature;
float rate = data->flow_rate;
float mflowrate = data->mass_flow_rate;
float setpoint = data->setpoint;
}
}
return 0;
}
Upgrade of Apirl 13:
I was checking the code of your classe alicat and i found it:
Data *alicat::get_data(){
alicat_data* ac_data = new alicat_data(0, 0, 0, 0, 0, Air);
alicat_data addr_data = parse_data(port->async_rw(string(1, address)));
ac_data = &addr_data;
return (Data*) ac_data;
}
I notice that you are returning a address of a local variable, ac_data = &addr_data;, that will be deleted after the method Data *alicat::get_data() is finished. That is the reason that you have a mess with data that you getting after invoke getData.
To fix it you must avoid return local variables because they are destroyed after onece the program get out of the context. Return an instance that is previously reserved with the operator new. At the moment that the object is destroyed you have the symptoms that you describe.
I notice that you have the same problem in the method alicat_data alicat::parse_data(const std::string &msg).
UPDATE: Considere this:
I'm not sure why did you get that behaivor, but i know that the local variable ac_data is delete after the context of getData is over but the memory that you allocate intoparse_data is still there, when you are returning the address of that local variable, return (Data*) ac_data; its memory released (a block of memor that is allocated into the stack and not into the heap) and it could be the reason that you are see garbage but when you use alicat_data data_ = *data; you are rescue the memory Block allocated into parse_data... How!? That si a good question and it coul be depend of compilar but the way you can prove it is debugging and be careful of each memory address that you are getting in:
The addres of memory that is allocated into parse_data
The address
of pointer that is returned to getData from parse_data`.
The
address of memory that is set to local variable alicat_data
addr_data into getData. The address of pointer of the local
variable alicat_data addr_data that is returned from getData.
Once you leave getData, compare the addres of the pointer
alicat_data *data vs the address of pointer that you got in
parse_data and compare the address.
Related
There is atomicAdd and atomicSub but it seems that atomicMul and atomicDiv don't exist! Is it possible? I need to implement the following code:
atomicMul(&accumulation[index],value)
How Can I do?
Ok, I solved. But I cannot understand how atomicMul works and I don't know how to write it for floats.
#include <stdio.h>
#include <cuda_runtime.h>
__device__ double atomicMul(double* address, double val)
{
unsigned long long int* address_as_ull = (unsigned long long int*)address;
unsigned long long int old = *address_as_ull, assumed;
do {
assumed = old;
old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val * __longlong_as_double(assumed)));
} while (assumed != old); return __longlong_as_double(old);
}
__global__ void try_atomicMul(double* d_a, double* d_out)
{
atomicMul(d_out,d_a[threadIdx.x]);
}
int main()
{
double h_a[]={5,6,7,8}, h_out=1;
double *d_a, *d_out;
cudaMalloc((void **)&d_a, 4 * sizeof(double));
cudaMalloc((void **)&d_out,sizeof(double));
cudaMemcpy(d_a, h_a, 4 * sizeof(double),cudaMemcpyHostToDevice);
cudaMemcpy(d_out, &h_out, sizeof(double),cudaMemcpyHostToDevice);
dim3 blockDim(4);
dim3 gridDim(1);
try_atomicMul<<<gridDim, blockDim>>>(d_a,d_out);
cudaMemcpy(&h_out, d_out, sizeof(double), cudaMemcpyDeviceToHost);
printf("%f \n",h_out);
cudaFree(d_a);
return 0;
}
I'll supplement horus' answer based on what I understood about atomicCAS. My answer can be wrong in detail, because I didn't look inside the atomicCAS function but just read the documents about it (atomicCAS, Atomic Functions). Feel free to tackle my answer.
How atomicMul works
According to my understanding, the behavior of atomicCAS(int* address, int compare, int val) is following.
Copy *address into old (i.e old = *address)
Store (old == compare ? val : old) to *address. (At this point, the value of old and *address can be different depending on if the condition matched or not.)
Return old
Understanding about its behavior gets better when we look at the atomicMul function's definition together.
unsigned long long int* address_as_ull = (unsigned long long int*)address;
unsigned long long int oldValue = *address_as_ull, assumed; // Modified the name 'old' to 'oldValue' because it can be confused with 'old' inside the atomicCAS.
do {
assumed = oldValue;
// other threads can access and modify value of *address_as_ull between upper and lower line.
oldValue = atomicCAS(address_as_ull, assumed, __double_as_longlong(val *
__longlong_as_double(assumed)));
} while (assumed != oldValue); return __longlong_as_double(oldValue);
What we want to do is read the value from address(its value is eqaul to address_as_ull), and multiply some value to it and then write it back. The problem is other threads can access and modify value of *address between read, modify, and write.
To ensure there was no intercept of other threads, we check if the value of *address is equal to what we assumed to be there. Say that other thread modified value of *address after assumed=oldValue and oldValue = atomicCAS(...). The modified value of *address will be copied to old variable inside the atomicCAS(see behavior 1. of atomicCAS above).
Since atomicCAS updates *address according to *address = (old == compare ? val : old), *address won't be changed (old==*address).
Then atomicCAS returns old and it goes into oldValue so that the loop can keep going and we can try another shot at next iteration. When *addressis not modified between read and write, then val is written to the *address and loop will end.
How to write it for float
short answer :
__device__ float atomicMul(float* address, float val)
{
int* address_as_int = (int*)address;
int old = *address_as_int, assumed;
do {
assumed = old;
old = atomicCAS(address_as_int, assumed, __float_as_int(val *
__float_as_int(assumed)));
} while (assumed != old); return __int_as_float(old);
}
I didn't test it, so there can be some errors. Fix me if I'm wrong.
How does it work :
For some reason, atomicCAS only supports integer types. So we should manually convert float/double type variable into integer type to input to the function and then re-convert the integer result to float/double type. What I've modified above is double to float and unsigned long long to int because the size of float matches to int.
Kyungsu's answer was almost correct. On the line defining old == atomicCAS(...) though, he used __float_as_int when he should have used __int_as_float. I corrected his code below:
__device__ float atomicMul(float* address, float val){
//Implementation of atomic multiplication
//See https://stackoverflow.com/questions/43354798/atomic-multiplication-and-division
int* address_as_int = (int*)address;
int old = *address_as_int;
int assumed;
do {
assumed = old;
old = atomicCAS(address_as_int, assumed, __float_as_int(val * __int_as_float(assumed)));
} while (assumed != old);
return __int_as_float(old);}
I am trying to convert a SAFEARRAY data pointer to unsinged char*. However I am not getting the expected data. Here is a snippet.
SafeArrayLock(psaFrameData);
psaFrameData->rgsabound->cElements;
int nCount = psaFrameData->rgsabound->cElements - psaFrameData->rgsabound->lLbound + 1;
frameData = new unsigned char[nCount];
memset(frameData, 0, nCount);
for (int i = 0; i < nCount; ++i)
{
frameData[i] = ((unsigned char*)(psaFrameData)->pvData)[i];
}
SafeArrayUnlock(psaFrameData);
Do not manually lock the array and then access its pvData (or any of its other data members) directly. Use the various accessors functions instead, such as SafeArrayAccessData():
Increments the lock count of an array, and retrieves a pointer to the array data.
Try something more like this:
// safety check: make sure the array has only 1 dimension...
if (SafeArrayGetDim(psaFrameData) != 1)
{
// handle the error ...
}
else
{
// safety check: make sure the array contains byte elements...
VARTYPE vt = 0;
SafeArrayGetVartype(psaFrameData, &vt);
if (vt != VT_UI1)
{
// handle the error ...
}
else
{
// get a pointer to the array's byte data...
unsigned char *data;
if (FAILED(SafeArrayAccessData(psaFrameData, (void**)&data)))
{
// handle the error ...
}
else
{
// calculate the number of bytes in the array...
LONG lBound, uBound;
SafeArrayGetLBound(psaFrameData, 1, &lBound);
SafeArrayGetUBound(psaFrameData, 1, &uBound);
long nCount = uBound - lBound + 1;
// copy the bytes...
frameData = new unsigned char[nCount];
memcpy(frameData, data, nCount);
// release the pointer to the array's byte data...
SafeArrayUnaccessData(psaFrameData);
}
}
}
first of all I admit I'm a newbie in C++ addons for node.js.
I'm writing my first addon and I reached a good result: the addon does what I want. I copied from various examples I found in internet to exchange complex data between the two languages, but I understood almost nothing of what I wrote.
The first thing scaring me is that I wrote nothing that seems to free some memory; another thing which is seriously worrying me is that I don't know if what I wrote may helps or creating confusion for the V8 garbage collector; by the way I don't know if there are better ways to do what I did (iterating over js Object keys in C++, creating js Objects in C++, creating Strings in C++ to be used as properties of js Objects and what else wrong you can find in my code).
So, before going on with my job writing the real math of my addon, I would like to share with the community the nan and V8 part of it to ask if you see something wrong or that can be done in a better way.
Thank you everybody for your help,
iCC
#include <map>
#include <nan.h>
using v8::Array;
using v8::Function;
using v8::FunctionTemplate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Value;
using v8::String;
using Nan::AsyncQueueWorker;
using Nan::AsyncWorker;
using Nan::Callback;
using Nan::GetFunction;
using Nan::HandleScope;
using Nan::New;
using Nan::Null;
using Nan::Set;
using Nan::To;
using namespace std;
class Data {
public:
int dt1;
int dt2;
int dt3;
int dt4;
};
class Result {
public:
int x1;
int x2;
};
class Stats {
public:
int stat1;
int stat2;
};
typedef map<int, Data> DataSet;
typedef map<int, DataSet> DataMap;
typedef map<float, Result> ResultSet;
typedef map<int, ResultSet> ResultMap;
class MyAddOn: public AsyncWorker {
private:
DataMap *datas;
ResultMap results;
Stats stats;
public:
MyAddOn(Callback *callback, DataMap *set): AsyncWorker(callback), datas(set) {}
~MyAddOn() { delete datas; }
void Execute () {
for(DataMap::iterator i = datas->begin(); i != datas->end(); ++i) {
int res = i->first;
DataSet *datas = &i->second;
for(DataSet::iterator l = datas->begin(); l != datas->end(); ++l) {
int dt4 = l->first;
Data *data = &l->second;
// TODO: real population of stats and result
}
// test result population
results[res][res].x1 = res;
results[res][res].x2 = res;
}
// test stats population
stats.stat1 = 23;
stats.stat2 = 42;
}
void HandleOKCallback () {
Local<Object> obj;
Local<Object> res = New<Object>();
Local<Array> rslt = New<Array>();
Local<Object> sts = New<Object>();
Local<String> x1K = New<String>("x1").ToLocalChecked();
Local<String> x2K = New<String>("x2").ToLocalChecked();
uint32_t idx = 0;
for(ResultMap::iterator i = results.begin(); i != results.end(); ++i) {
ResultSet *set = &i->second;
for(ResultSet::iterator l = set->begin(); l != set->end(); ++l) {
Result *result = &l->second;
// is it ok to declare obj just once outside the cycles?
obj = New<Object>();
// is it ok to use same x1K and x2K instances for all objects?
Set(obj, x1K, New<Number>(result->x1));
Set(obj, x2K, New<Number>(result->x2));
Set(rslt, idx++, obj);
}
}
Set(sts, New<String>("stat1").ToLocalChecked(), New<Number>(stats.stat1));
Set(sts, New<String>("stat2").ToLocalChecked(), New<Number>(stats.stat2));
Set(res, New<String>("result").ToLocalChecked(), rslt);
Set(res, New<String>("stats" ).ToLocalChecked(), sts);
Local<Value> argv[] = { Null(), res };
callback->Call(2, argv);
}
};
NAN_METHOD(AddOn) {
Local<Object> datas = info[0].As<Object>();
Callback *callback = new Callback(info[1].As<Function>());
Local<Array> props = datas->GetOwnPropertyNames();
Local<String> dt1K = Nan::New("dt1").ToLocalChecked();
Local<String> dt2K = Nan::New("dt2").ToLocalChecked();
Local<String> dt3K = Nan::New("dt3").ToLocalChecked();
Local<Array> props2;
Local<Value> key;
Local<Object> value;
Local<Object> data;
DataMap *set = new DataMap();
int res;
int dt4;
DataSet *dts;
Data *dt;
for(uint32_t i = 0; i < props->Length(); i++) {
// is it ok to declare key, value, props2 and res just once outside the cycle?
key = props->Get(i);
value = datas->Get(key)->ToObject();
props2 = value->GetOwnPropertyNames();
res = To<int>(key).FromJust();
dts = &((*set)[res]);
for(uint32_t l = 0; l < props2->Length(); l++) {
// is it ok to declare key, data and dt4 just once outside the cycles?
key = props2->Get(l);
data = value->Get(key)->ToObject();
dt4 = To<int>(key).FromJust();
dt = &((*dts)[dt4]);
int dt1 = To<int>(data->Get(dt1K)).FromJust();
int dt2 = To<int>(data->Get(dt2K)).FromJust();
int dt3 = To<int>(data->Get(dt3K)).FromJust();
dt->dt1 = dt1;
dt->dt2 = dt2;
dt->dt3 = dt3;
dt->dt4 = dt4;
}
}
AsyncQueueWorker(new MyAddOn(callback, set));
}
NAN_MODULE_INIT(Init) {
Set(target, New<String>("myaddon").ToLocalChecked(), GetFunction(New<FunctionTemplate>(AddOn)).ToLocalChecked());
}
NODE_MODULE(myaddon, Init)
One year and half later...
If somebody is interested, my server is up and running since my question and the amount of memory it requires is stable.
I can't say if the code I wrote really does not has some memory leak or if lost memory is freed at each thread execution end, but if you are afraid as I was, I can say that using same structure and calls does not cause any real problem.
You do actually free up some of the memory you use, with the line of code:
~MyAddOn() { delete datas; }
In essence, C++ memory management boils down to always calling delete for every object created by new. There are also many additional architecture-specific and legacy 'C' memory management functions, but it is not strictly necessary to use these when you do not require the performance benefits.
As an example of what could potentially be a memory leak: You're passing the object held in the *callback pointer to the function AsyncQueueWorker. Yet nowhere in your code is this pointer freed, so unless the Queue worker frees it for you, there is a memory leak here.
You can use a memory tool such as valgrind to test your program further. It will spot most memory problems for you and comes highly recommended.
One thing I've observed is that you often ask (paraphrased):
Is it okay to declare X outside my loop?
To which the answer actually is that declaring variables inside of your loops is better, whenever you can do it. Declare variables as deep inside as you can, unless you have to re-use them. Variables are restricted in scope to the outermost set of {} brackets. You can read more about this in this question.
is it ok to use same x1K and x2K instances for all objects?
In essence, when you do this, if one of these objects modifies its 'x1K' string, then it will change for all of them. The advantage is that you free up memory. If the string is the same for all these objects anyway, instead of having to store say 1,000,000 copies of it, your computer will only keep a single one in memory and have 1,000,000 pointers to it instead. If the string is 9 ASCII characters long or longer under amd64, then that amounts to significant memory savings.
By the way, if you don't intend to modify a variable after its declaration, you can declare it as const, a keyword short for constant which forces the compiler to check that your variable is not modified after declaration. You may have to deal with quite a few compiler errors about functions accepting only non-const versions of things they don't modify, some of which may not be your own code, in which case you're out of luck. Being as conservative as possible with non-const variables can help spot problems.
I am using gSOAP to configure an ONVIF compatible camera.
Currently, I am manually setting all the parameters in the request by doing something like this. This is for the SetVideEncoderConfiguration
MediaBindingProxy mediaDevice (uri);
AUTHENTICATE (mediaDevice);
_trt__SetVideoEncoderConfiguration req;
_trt__SetVideoEncoderConfigurationResponse resp;
struct tt__VideoEncoderConfiguration encoderConfig;
struct tt__VideoResolution resolutionConfig;
encoderConfig.Name = strdup (name);
encoderConfig.UseCount = 1;
encoderConfig.Quality = 50;
if (strcmp (encoding, "H264") == 0)
encoderConfig.Encoding = tt__VideoEncoding__H264;
else if (strcmp (encoding, "JPEG") == 0)
encoderConfig.Encoding = tt__VideoEncoding__JPEG;
encoderConfig.token = strdup (profileToken);
encoderConfig.SessionTimeout = (LONG64)"PT0S";
resolutionConfig.Width=1280;
resolutionConfig.Height=720;
encoderConfig.Resolution = &resolutionConfig;
tt__VideoRateControl rateControl;
rateControl.FrameRateLimit = 15;
rateControl.EncodingInterval = 1;
rateControl.BitrateLimit = 4500;
encoderConfig.RateControl = &rateControl;
struct tt__H264Configuration h264;
h264.GovLength = 30;
h264.H264Profile = tt__H264Profile__Baseline;
encoderConfig.H264 = &h264;
struct tt__MulticastConfiguration multicast;
struct tt__IPAddress address;
address.IPv4Address = strdup ("0.0.0.0");
multicast.Address = &address;
encoderConfig.Multicast = &multicast;
req.Configuration = &encoderConfig;
req.ForcePersistence = true;
int ret = mediaDevice.SetVideoEncoderConfiguration (&req, resp);
qDebug () << "Set Encoder: " << ret;
Is there an easier way to do this? May be some function calls that set the request parameters? Another way I found with GetMediaUri was to use something like
soap_new_req__trt__GetStreamUri (mediaDevice.soap,soap_new_req_tt__StreamSetup (mediaDevice.soap, (enum tt__StreamType)0, soap_new_tt__Transport(mediaDevice.soap), 1, NULL), "profile1");
Are these the only two ways for client side code with gSOAP?
-Mandar Joshi
There are four variations of soap_new_T() to allocate data of type T in C++ with gSOAP:
T * soap_new_T(struct soap*) returns a new instance of T that is default
initialized and allocated on the heap managed by the soap context.
T * soap_new_T(struct soap*, int n) returns an array of n new instances of
T on the managed heap. The instances in the array are default initialized as described above.
T * soap_new_req_T(struct soap*, ...) (structs and classes only) returns a
new instance of T allocated on the managed heap and sets the required data members to the values specified in the other arguments ....
T * soap_new_set_T(struct soap*, ...) (structs and classes only) returns a
new instance of T on the managed heap and sets the public/serializable data members to the values specified in the other arguments ....
Use soap_strdup(struct soap*, const char*) instead of strdup to dup strings onto the managed heap.
All data on the managed heap is mass-deleted with soap_destroy(soap) and
soap_end(soap) (call these in that order) which must be called before soap_done(soap) or soap_free(soap).
To allocate pointers to data, use templates:
template<class T>
T * soap_make(struct soap *soap, T val)
{
T *p = (T*)soap_malloc(soap, sizeof(T));
if (p)
*p = val;
return p;
}
template<class T>
T **soap_make_array(struct soap *soap, T* array, int n)
{
T **p = (T**)soap_malloc(soap, n * sizeof(T*));
for (int i = 0; i < n; ++i)
p[i] = &array[i];
return p;
}
Then use soap_make<int>(soap, 123) to create a pointer to the value 123 on the managed heap and soap_make_array(soap, soap_new_CLASSNAME(soap, 100), 100) to create 100 pointers to 100 instances of CLASSNAME.
The gSOAP tools also generate deep copy operations for you: CLASSNAME::soap_dup(struct soap*) creates a deep copy of the object and allocates it in a another soap context that you provide as argument. Use NULL as this argument to allocate unmanaged deep copies (but these cannot have pointer cycles!). Then delete unmanaged copies with CLASSNAME::soap_del() for deep deletion of all members and then delete the object itself.
See Memory management in C++ for more details. Use gSOAP 2.8.39 and greater.
I was reading on the explanation of container_of macro and I got most of it except one thing. How does inode->I_cdev point to cdev?
To be sure the cdev here is the character device we initialized in our cdev_init call .
one more thing to add
dev in "struct cdev" is DD point of view and dev_t in "struct inode" is Fs( file system) point of view.
also the Struct inode ( part of fs.h) ---> struct cdev(part of cdev.h & Member object of struct Inode ) ---> ( major , minor )
& the Struct Dev ( user defined ) ---> struct cdev---> ( major , minor)
both reaches the same point .
if you look in chrdev_open function under fs/char_dev.c file you will see that before opening any character device, its respective i_cdev structure is populated in inode's structure.
p = inode->i_cdev;
if (!p) {
struct kobject *kobj;
int idx;
spin_unlock(&cdev_lock);
kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
if (!kobj)
return -ENXIO;
new = container_of(kobj, struct cdev, kobj);
spin_lock(&cdev_lock);
/* Check i_cdev again in case somebody beat us to it while
we dropped the lock. */
p = inode->i_cdev;
if (!p) {
inode->i_cdev = p = new;
list_add(&inode->i_devices, &p->list);
new = NULL;
} else if (!cdev_get(p))
ret = -ENXIO;
} else if (!cdev_get(p))
ret = -ENXIO;
Well for the inode itself, it must be created when a device node is created.
I dont know much about kobjects, but its some how getting the cdev using kobj, and where we associated that kobject with this perticular device? the answer lies in cdev_add
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
int error;
p->dev = dev;
p->count = count;
error = kobj_map(cdev_map, dev, count, NULL,
exact_match, exact_lock, p);
if (error)
return error;
kobject_get(p->kobj.parent);
return 0;
}