I am configuring my MPI_Info with the hosts where the processes will be spawned (MPI_Comm Spawn).
The problem is that when I use a big amount of processes the setting is not performed correctly, throwing this error:
Fatal error in MPI_Info_set: Invalid MPI_Info value , error stack:
MPI_Info_set(117): MPI_Info_set(info=0x9c000000, key=hosts, value=cuda00,cuda00,cuda00,cuda00,cuda00,cuda00,cuda00,cuda00,cuda01,cuda01,cuda01,cuda01,cuda01,cuda01,cuda01,cuda01,cuda02,cuda02,cuda02,cuda02,cuda02,cuda02,cuda02,cuda02,cuda03,cuda03,cuda03,cuda03,cuda04,cuda0
MPI_Info_set(97).: Value is too long
The field "value" is the hostlist and this hostlist is assigned to the MPI_Info structure with:
MPI_Info_set(info, "hosts", mpihosts);
where "mpihosts" is a char*.
Can I change the capacity of MPI_Info?
Indeed, there an hard-coded maximal length for the string describing the values in MPI_INFO. It is defined in mpi.h and it is named MPI_MAX_INFO_VAL. According to the MPI standards, at the beginning of chapter 9 (p397):
values have an implementation-defined maximum length
of MPI_MAX_INFO_VAL... ... If either key or value are larger than the allowed maximums, the errors MPI_ERR_INFO_KEY or MPI_ERR_INFO_VALUE are raised, respectively.
Let's print this value: by trying printf("MPI_MAX_INFO_VAL is %d\n",MPI_MAX_INFO_VAL);, my openmpi value is 256... There is a line #define MPI_MAX_INFO_VAL 1024 in the file mpich3-2/src/include/mpi.h.in of MPICH2. As a result, the list of the hostname can be too long to be stored as the value of a key in an MPI_INFO structure.
As an alternative, the list of the hosts can be stored in a file and the name of the file can be provided to MPI_Comm_spawn() as the value of the key hostfile of the MPI_INFO structure, as detailed in the documentation of OpenMPI
Taking #francis' comments into account, I decided to give other approach to the problem.
Since MPI_MAX_INFO_VAL cannot be altered and MPI_Info_set(info, "hostfile", filename) is ignored, I must use MPI_Comm_spawn_multiple().
MPI_Comm_spawn_multiple() expects a number of nodes and several arrays of that length.
For this solution I keep focus on the MPI_Info field, that now is an array which can be set like that:
MPI_info *infos = malloc(sizeof (MPI_Info) * nodecnt);
for (i = 0; i < nodecnt; i++) {
MPI_Info_create(&infos[i]);
MPI_Info_set(infos[i], "hosts", hostnames[i]);
}
nodecnt is the total amount of nodes to spawn the new processes.
hostnames is an array of strings which have the host name repeated (separated by commas) as many times as processes will be spawned in that host.
So, in our call to MPI_Comm_spawn_multiple() we will use the variable infos.
Mine is similar to this:
MPI_Comm_spawn_multiple(nodecnt, commands, MPI_ARGVS_NULL, maxprocs, infos, 0, MPI_COMM_WORLD, &newcomm, MPI_ERRCODES_IGNORE);
By the way, it is true that this does not solve the problem completely, due to with a very long list of host names, we would get the same problem. However, this solution give us more room have for manoeuvre.
Related
I have built a libpcre2-8.dll with the help of this Git Repo.
I'm now trying to access the function pcre2_compile from an ABL (Progress) program. (Progress is an old 4GL Language). I'm constantly hitting the error
Could not find the entrypoint _pcre2_compile#40. (3260)
I've already tried many things but it still doesn't work.
The Dynamic Library is 64 bit and Progress is also running in 64 bit.
In ABL (Progress) you can specify the LIBRARY-CALLING-CONVENTION but whether I set it to STDCALL or CDECL or just don't specify it, the error remains the same.
This is a snippet of the Progress ABL I'm trying to execute the function: (code comes from this Git Repo, which works, but only for 32 bit)
PROCEDURE pcre2_compile :
DEFINE INPUT PARAMETER pattern AS CHARACTER. /* const char * */
DEFINE INPUT PARAMETER options AS INTEGER. /* int */
DEFINE OUTPUT PARAMETER errcodeptr AS INTEGER. /* int * */
DEFINE OUTPUT PARAMETER errptr AS MEMPTR. /* const char ** */
DEFINE OUTPUT PARAMETER erroffset AS MEMPTR. /* int * */
DEFINE INPUT PARAMETER tableptr AS INTEGER. /* const unsigned char * */
DEFINE OUTPUT PARAMETER result AS MEMPTR. /* pcre * */
DEFINE VARIABLE libName AS CHARACTER NO-UNDO.
DEFINE VARIABLE hCall AS HANDLE NO-UNDO.
libName = get-library().
CREATE CALL hCall.
ASSIGN
hCall:CALL-NAME = "pcre2_compile"
hCall:LIBRARY = "lib/libpcre2-8.dll"
//hCall:LIBRARY-CALLING-CONVENTION = "STDCALL"
hCall:CALL-TYPE = DLL-CALL-TYPE
hCall:NUM-PARAMETERS = 6
hCall:RETURN-VALUE-DLL-TYPE = "MEMPTR".
hCall:SET-PARAMETER(1, "CHARACTER", "INPUT" , pattern ).
hCall:SET-PARAMETER(2, "LONG" , "INPUT" , options ).
hCall:SET-PARAMETER(3, "HANDLE TO LONG" , "OUTPUT", errcodeptr ).
hCall:SET-PARAMETER(4, "MEMPTR" , "OUTPUT", errptr ).
hCall:SET-PARAMETER(5, "MEMPTR" , "OUTPUT", erroffset ).
hCall:SET-PARAMETER(6, "LONG" , "INPUT" , tableptr ).
hCall:INVOKE().
ASSIGN result = hCall:RETURN-VALUE.
DELETE OBJECT hCall.
END PROCEDURE.
What am I missing?
Update: Checked with Dependency Walker and the functions seem to be visible. They do have a _8 suffix... But even when trying pcre2_compile_8 it still gives me the same error.
I think that you need to change your long integers to INT64.
Is the entrypoint externally visible/accesible?
I've used https://dependencywalker.com/ in the past to figure that out.
Does that change if you specify the ORDINAL option ?
So the problem was that the name of the entry point was "pcre2_compile_8" instead of "pcre2_compile"... Wanted to delete the question because now it looks quite dumb but leaving it anyway...
I write a driver in windows, and I need disk drive serial number, for user mode I found this ansver.
My question is it possible to translate the above code to kernel mode, and how? Is WMI query available in filter driver? Sample code can greatly help.
EDIT:
I found here this code, but how I rewrite him for get serial number?
void GetSmbios()
{
NTSTATUS status;
GUID smbiosGUID = SMBIOS_DATA_GUID; // defined in wmiguid.h
PVOID wmiObject = NULL;
PWNODE_ALL_DATA dataBuffer;
ULONG bufferSize;
int TAG_SMBIOS = 'smbi';
//
// Get a WMI block handle to the SMBIOS_DATA_GUID
//
status = IoWMIOpenBlock((GUID *)&smbiosGUID, WMIGUID_QUERY,
&wmiObject);
if (!NT_SUCCESS(status))
{
return status;
}
//
// Determine how much space is required for the data
//
status = IoWMIQueryAllData(wmiObject, &bufferSize, NULL);
if (status != STATUS_BUFFER_TOO_SMALL)
{
ObDereferenceObject(wmiObject);
return status;
}
//
// Allocate the necessary storage. This space must come out of NP-pool
//
dataBuffer = ExAllocatePoolWithTag(
NonPagedPool,
bufferSize,
TAG_SMBIOS);
if (dataBuffer == NULL)
{
ObDereferenceObject(wmiObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
}
After allocating memory, I believe you need to call IoWMIQueryAllData() again, this time passing dataBuffer.
SMBIOS doesn't seem related to disk drives, so you'll want a different GUID to pass to IoWMIOpenBlock(). Perhaps this one ({BF253431-1E4D-4F57-00E7-64B2CACC801E}), since your user-mode example and others query Win32_PhysicalMedia to get SerialNumber.
However, this references a (presumably user-mode) DLL that is the provider for Win32_PhysicalMedia. So this may not be accessible in kernel-mode.
But it also gives a hint how to get the information from kernel-mode: IOCTLs. It mentions IOCTL_SMART_GET_VERSION, which should be just SMART_GET_VERSION, and here's an example:
(in user-mode, but you should be able to do similar from kernel-mode using ZwDeviceIoControlFile()). Note it follows up with another ioctl command, SMART_RCV_DRIVE_DATA, to get the serial number.
Another ioctl that sounds promising (and more general) is IOCTL_STORAGE_QUERY_PROPERTY, with the input STORAGE_PROPERTY_QUERY.PropertyId set to StorageDeviceProperty, so the output will be a STORAGE_DEVICE_DESCRIPTOR structure, which has field SerialNumberOffset:
Specifies the byte offset from the beginning of the structure to a null-terminated ASCII string that contains the device's serial number. If the device has no serial number, this member is zero.
FILE_FS_VOLUME_INFORMATION contains field VolumeSerialNumber. This data structure might be retrieved with ZwQueryVolumeInformationFile(... FileFsVolumeInformation).
That requires a handle to the volume or a file/directory in the volume. If that's not feasible, but you have a DEVICE_OBJECT, you might try building your own IRP with IRP_MJ_QUERY_VOLUME_INFORMATION and sending it with IoCallDriver(), though I don't know if that's sanctioned -- the docs say such a "request is sent by the I/O Manager."
I want to make a program (network server-client).
One of the specification for this program is next:
The server will receive the sent packages and save it into a file, with a unique name (generated by the server at the moment the transfer starts.
Ex __tf_"unique_random_string".txt
I made a function that returns a pointer to a "unique" string created.
The problem is: If i stop the server and then start it again it will generate the same names.
Ex:this file names were generated and then i stopped the server.
__ft_apqfwk.txt
__ft_arzowk.txt
__ft_cdyggx.txt
I start it again and i try to generate 3 file names. Them will be the same.
Sorry for my english. I'm still learning it.
My function to generate this "unique string" is:
char *create_random_name(void)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
char *file_name;
int i=0;
int key;
if((file_name = malloc(16 * sizeof ( char )) ) == NULL)
{
printf("Failed to alloc memory space\n");
return NULL;
}
strcpy(file_name,"__ft_");
for(i=5 ; i<11 ; i++)
{
key = rand() % (int)(sizeof(charset)-1);
file_name[i]=charset[key];
}
strcat(file_name,".txt");
file_name[15] = '\0';
return file_name;
}
One option is saving to a file the names that have been used, and using them as a checklist. You also want to seed rand with something like srand(time(NULL)).
another is ignoring the randomisation, and just going in order, e.g. aaa, aab aac...aba ,abb etc. Again, save where your cycle is up to on a file.
Your question seems a little bit unclear but if you want to generate a unique string there are a couple of things you can consider:
Get System timestamp ( yyyy-MM-dd-HH-mm-ss-fff-tt)
Use Random function to generate a random number
Combine this with your function and I am sure you will get a unique string.
Hope it helps !
If it's available, you could avoid manually generating random names that might collide and let the system do it for you (and handle collision resolution by creating a new name) by using mkstemps. This is also safer because it opens the file for you, removing the risk of a random name being generated, verified to be unique, then trying to open it and discovering another thread/process raced in and created it.
char name[] = "/path/to/put/files/in/__ft_XXXXXX.txt";
int fd = mkstemps(name, strlen(".txt"));
if (fd == -1) { ... handle error ... }
After mkstemps succeeds, name will hold the path to the file (it's mutated in place, replacing the XXXXXX string), and fd will be an open file descriptor to that newly created file; if you need a FILE*, use fdopen to convert to a stdio type.
Before calling rand(),--- once and only once---, call srand(time()) to initialize the random number generator.
Before settling on any specific file name, call stat() to assure that file name does not already exist.
I tried to extend the 'iw' utility to allow it to set the maximum and minimum size of the 802.11 contention window. But I'm always getting a 'invalid argument (-22)' returned.
I edited phy.c of the iw-3.15 source and appended
static int handle_txq(struct nl80211_state *state,
struct nl_cb *cb,
struct nl_msg *msg,
int argc, char **argv,
enum id_input id)
{
unsigned int cw_min, cw_max;
printf("HANDLE TXQ");
if (argc != 2)
return 1;
cw_min = atoi(argv[0]);
cw_max = atoi(argv[1]);
printf("setting contention window to: %d - %d\n",cw_min,cw_max);
//create nested txq array
struct nlattr *nested;
nested = nla_nest_start(msg,NL80211_ATTR_WIPHY_TXQ_PARAMS);
NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMIN,cw_min);
NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMAX,cw_max);
nla_nest_end(msg,nested);
return 0;
nla_put_failure:
return -ENOBUFS;
}
COMMAND(set, txq, "<cw_min> <cw_max>",
NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txq,
"Set contention window minimum and maximum size.\n"
"Valid values: 1 - 32767 in the form 2^n-1");
COMMAND(set, txq, "<cw_min> <cw_max>",
NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txq,
"Set contention window minimum and maximum size.\n"
"Valid values: 1 - 32767 in the form 2^n-1");
I couldn't find any good documentation of nl80211 or it's usage through netlink except the header file itself. I am not
sure if I contruct the nested message according to specification and using U16 for the attributes are an educated guess (they are uint_16 in the matching cfg80211).
From my understanding of netlink my message assembly should be correct, but since I get an error I'm probably wrong...
Does anyone have a good documentation for nl80211 and its usage? Can anyone spot my problem?
From the kernel code on the other end of the netlink socket (in linux/net/wireless/nl80211.c - I am using 3.13.0-30), it seems there are a few reasons you can get an "invalid argument" (-EINVAL) response.
Firstly, you need to give it a valid interface and the device needs to be in AP or P2P_GO mode. You also need to provide all the TXQ params, not just contention window values. See the nl80211_set_wiphy() and parse_txq_params() functions in nl80211.c if you want to see exactly how your message is being handled.
You do appear to be using the correct types for the parameters though: NL80211_TXQ_ATTR_QUEUE/NL80211_TXQ_ATTR_AC (depending on version) and NL80211_TXQ_ATTR_AIFS are u8, and the other three (NL80211_TXQ_ATTR_TXOP, NL80211_TXQ_ATTR_CWMIN and NL80211_TXQ_ATTR_CWMAX) are u16.
Can anybody tell me why the following code doesn't work? I don't get any compiler errors.
short value = 10;
SetProp(hCtl, "value", (short*) value);
The third parameter is typed as a HANDLE, so IMO to meet the explicit contract of the function you should save the property as a HANDLE by allocating a HGLOBAL memory block. However, as noted in the comments below, MSDN states that any value can be specified, and indeed when I try it on Windows 7 using...
SetProp(hWnd, _T("TestProp"), (HANDLE)(10)); // or (HANDLE)(short*)(10)
...
(short)GetProp(hWnd, _T("TestProp"));
... I get back 10 from GetProp. I suspect somewhere between your SetProp and GetProp one of two things happens: (1) the value of hWnd is different -- you're checking a different window or (2) a timing issue -- the property hasn't been set yet or had been removed.
If you wanted to use an HGLOBAL instead to follow the specific types of the function signature, you can follow this example in MSDN.
Even though a HANDLE is just a pointer, it's a specific data type that is allocated by calls into the Windows API. Lots of things have handles: icons, cursors, files, ... Unless the documentation explicitly states otherwise, to use a blob of data such as a short when the function calls for a HANDLE, you need a memory handle (an HGLOBAL).
The sample code linked above copies data as a string, but you can instead set it as another data type:
// TODO: Add error handling
hMem = GlobalAlloc(GPTR, sizeof(short));
lpMem = GlobalLock(hMem);
if (lpMem != NULL)
{
*((short*)lpMem) = 10;
GlobalUnlock(hMem);
}
To read it back, when you GetProp to get the HANDLE you must lock it to read the memory:
// TODO: Add error handling
short val;
hMem = (HGLOBAL)GetProp(hwnd, ...);
if (hMem)
{
lpMem = GlobalLock(hMem);
if (lpMem)
{
val = *((short*)lpMem);
}
}
I would create the short on the heap, so that it continues to exist, or perhaps make it global, which is perhaps what you did. Also the cast for the short address needs to be void *, or HANDLE.